From 15d1cc806b1b978bab83d8bb426a124d9f0f788c Mon Sep 17 00:00:00 2001 From: gdkchan Date: Mon, 4 May 2020 00:41:29 -0300 Subject: [PATCH] Move kernel state out of the Horizon class (#1107) * Move kernel state from Horizon to KernelContext * Merge syscalls partial classes, split 32 and 64-bit variants * Sort usings --- Ryujinx.HLE/HOS/Horizon.cs | 159 +- Ryujinx.HLE/HOS/Kernel/Common/KAutoObject.cs | 16 +- .../HOS/Kernel/Common/KResourceLimit.cs | 16 +- .../Kernel/Common/KSynchronizationObject.cs | 4 +- .../HOS/Kernel/Common/KernelTransfer.cs | 20 +- Ryujinx.HLE/HOS/Kernel/Ipc/KClientPort.cs | 22 +- Ryujinx.HLE/HOS/Kernel/Ipc/KClientSession.cs | 10 +- .../HOS/Kernel/Ipc/KLightClientSession.cs | 4 +- .../HOS/Kernel/Ipc/KLightServerSession.cs | 4 +- Ryujinx.HLE/HOS/Kernel/Ipc/KLightSession.cs | 6 +- Ryujinx.HLE/HOS/Kernel/Ipc/KPort.cs | 14 +- Ryujinx.HLE/HOS/Kernel/Ipc/KServerPort.cs | 18 +- Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs | 94 +- Ryujinx.HLE/HOS/Kernel/Ipc/KSession.cs | 6 +- Ryujinx.HLE/HOS/Kernel/KernelConstants.cs | 16 + Ryujinx.HLE/HOS/Kernel/KernelContext.cs | 114 + .../HOS/Kernel/Memory/KMemoryManager.cs | 38 +- .../HOS/Kernel/Memory/KSharedMemory.cs | 12 +- .../HOS/Kernel/Memory/KTransferMemory.cs | 2 +- .../HOS/Kernel/Process/KHandleTable.cs | 17 +- Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs | 117 +- .../HOS/Kernel/SupervisorCall/SvcHandler.cs | 44 - .../HOS/Kernel/SupervisorCall/SvcIpc.cs | 607 ----- .../HOS/Kernel/SupervisorCall/SvcMemory.cs | 617 ----- .../HOS/Kernel/SupervisorCall/SvcSystem.cs | 732 ------ .../HOS/Kernel/SupervisorCall/SvcThread.cs | 520 ---- .../Kernel/SupervisorCall/SvcThreadSync.cs | 306 --- .../HOS/Kernel/SupervisorCall/Syscall.cs | 2090 +++++++++++++++++ .../HOS/Kernel/SupervisorCall/Syscall32.cs | 435 ++++ .../HOS/Kernel/SupervisorCall/Syscall64.cs | 338 +++ .../Kernel/SupervisorCall/SyscallHandler.cs | 57 + .../{SvcTable.cs => SyscallTable.cs} | 255 +- .../HOS/Kernel/Threading/KAddressArbiter.cs | 170 +- .../Kernel/Threading/KConditionVariable.cs | 20 +- .../HOS/Kernel/Threading/KCriticalSection.cs | 19 +- Ryujinx.HLE/HOS/Kernel/Threading/KEvent.cs | 6 +- .../HOS/Kernel/Threading/KReadableEvent.cs | 12 +- .../HOS/Kernel/Threading/KScheduler.cs | 14 +- .../HOS/Kernel/Threading/KSynchronization.cs | 28 +- Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs | 136 +- .../HOS/Kernel/Threading/KWritableEvent.cs | 4 +- Ryujinx.HLE/HOS/ProgramLoader.cs | 35 +- .../ILibraryAppletAccessor.cs | 6 +- .../SystemAppletProxy/IHomeMenuFunctions.cs | 2 +- .../SystemAppletProxy/ISelfController.cs | 4 +- .../ApplicationProxy/IApplicationFunctions.cs | 2 +- .../AudioRendererManager/IAudioDevice.cs | 2 +- .../AudioRendererManager/IAudioRenderer.cs | 2 +- .../HOS/Services/Audio/IAudioOutManager.cs | 2 +- .../IDeliveryCacheProgressService.cs | 2 +- .../Services/Bluetooth/IBluetoothDriver.cs | 12 +- .../BluetoothManager/BtmUser/IBtmUserCore.cs | 8 +- .../ServiceCreator/INotificationService.cs | 2 +- .../Services/Hid/HidDevices/NpadDevices.cs | 2 +- Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs | 4 +- Ryujinx.HLE/HOS/Services/IpcService.cs | 2 +- .../HOS/Services/Ldn/NetworkInterface.cs | 2 +- .../HOS/Services/Nfc/Nfp/UserManager/IUser.cs | 6 +- .../Services/Nifm/StaticService/IRequest.cs | 4 +- .../NvHostChannel/NvHostGpuDeviceFile.cs | 6 +- .../NvHostCtrl/Types/NvHostEvent.cs | 2 +- .../NvHostCtrlGpu/NvHostCtrlGpuDeviceFile.cs | 4 +- .../HOS/Services/Ptm/Psm/IPsmSession.cs | 2 +- Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs | 6 +- .../SurfaceFlinger/BufferQueueCore.cs | 4 +- .../Time/Clock/StandardUserSystemClockCore.cs | 2 +- .../Time/StaticService/ISystemClock.cs | 2 +- Ryujinx.HLE/HOS/SystemState/AppletStateMgr.cs | 2 +- 68 files changed, 3678 insertions(+), 3570 deletions(-) create mode 100644 Ryujinx.HLE/HOS/Kernel/KernelConstants.cs create mode 100644 Ryujinx.HLE/HOS/Kernel/KernelContext.cs delete mode 100644 Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs delete mode 100644 Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcIpc.cs delete mode 100644 Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcMemory.cs delete mode 100644 Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs delete mode 100644 Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs delete mode 100644 Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThreadSync.cs create mode 100644 Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs create mode 100644 Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs create mode 100644 Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs create mode 100644 Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallHandler.cs rename Ryujinx.HLE/HOS/Kernel/SupervisorCall/{SvcTable.cs => SyscallTable.cs} (53%) diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs index 37c3fba70..c6154b439 100644 --- a/Ryujinx.HLE/HOS/Horizon.cs +++ b/Ryujinx.HLE/HOS/Horizon.cs @@ -14,7 +14,7 @@ using Ryujinx.Common.Logging; using Ryujinx.Configuration; using Ryujinx.HLE.FileSystem.Content; using Ryujinx.HLE.HOS.Font; -using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Kernel.Threading; @@ -33,39 +33,26 @@ using Ryujinx.HLE.Loaders.Executables; using Ryujinx.HLE.Loaders.Npdm; using Ryujinx.HLE.Utilities; using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -using System.Threading; - -using TimeServiceManager = Ryujinx.HLE.HOS.Services.Time.TimeManager; -using NsoExecutable = Ryujinx.HLE.Loaders.Executables.NsoExecutable; -using JsonHelper = Ryujinx.Common.Utilities.JsonHelper; using static LibHac.Fs.ApplicationSaveDataManagement; namespace Ryujinx.HLE.HOS { + using TimeServiceManager = Services.Time.TimeManager; + using JsonHelper = Common.Utilities.JsonHelper; + public class Horizon : IDisposable { - internal const int InitialKipId = 1; - internal const int InitialProcessId = 0x51; - internal const int HidSize = 0x40000; internal const int FontSize = 0x1100000; internal const int IirsSize = 0x8000; internal const int TimeSize = 0x1000; - private const int MemoryBlockAllocatorSize = 0x2710; - - private const ulong UserSlabHeapBase = DramMemoryMap.SlabHeapBase; - private const ulong UserSlabHeapItemSize = KMemoryManager.PageSize; - private const ulong UserSlabHeapSize = 0x3de000; - - internal long PrivilegedProcessLowestId { get; set; } = 1; - internal long PrivilegedProcessHighestId { get; set; } = 8; + internal KernelContext KernelContext { get; } internal Switch Device { get; private set; } @@ -73,39 +60,6 @@ namespace Ryujinx.HLE.HOS public SystemStateMgr State { get; private set; } - internal bool KernelInitialized { get; private set; } - - internal KResourceLimit ResourceLimit { get; private set; } - - internal KMemoryRegionManager[] MemoryRegions { get; private set; } - - internal KMemoryBlockAllocator LargeMemoryBlockAllocator { get; private set; } - internal KMemoryBlockAllocator SmallMemoryBlockAllocator { get; private set; } - - internal KSlabHeap UserSlabHeapPages { get; private set; } - - internal KCriticalSection CriticalSection { get; private set; } - - internal KScheduler Scheduler { get; private set; } - - internal KTimeManager TimeManager { get; private set; } - - internal KSynchronization Synchronization { get; private set; } - - internal KContextIdManager ContextIdManager { get; private set; } - - private long _kipId; - private long _processId; - private long _threadUid; - - internal CountdownEvent ThreadCounter; - - internal SortedDictionary Processes; - - internal ConcurrentDictionary AutoObjectNames; - - internal bool EnableVersionChecks { get; private set; } - internal AppletStateMgr AppletState { get; private set; } internal KSharedMemory HidSharedMem { get; private set; } @@ -152,50 +106,15 @@ namespace Ryujinx.HLE.HOS { ControlData = new BlitStruct(1); + KernelContext = new KernelContext(device, device.Memory); + Device = device; State = new SystemStateMgr(); - ResourceLimit = new KResourceLimit(this); - - KernelInit.InitializeResourceLimit(ResourceLimit); - - MemoryRegions = KernelInit.GetMemoryRegions(); - - LargeMemoryBlockAllocator = new KMemoryBlockAllocator(MemoryBlockAllocatorSize * 2); - SmallMemoryBlockAllocator = new KMemoryBlockAllocator(MemoryBlockAllocatorSize); - - UserSlabHeapPages = new KSlabHeap( - UserSlabHeapBase, - UserSlabHeapItemSize, - UserSlabHeapSize); - - CriticalSection = new KCriticalSection(this); - - Scheduler = new KScheduler(this); - - TimeManager = new KTimeManager(); - - Synchronization = new KSynchronization(this); - - ContextIdManager = new KContextIdManager(); - - _kipId = InitialKipId; - _processId = InitialProcessId; - - Scheduler.StartAutoPreemptionThread(); - - KernelInitialized = true; - - ThreadCounter = new CountdownEvent(1); - - Processes = new SortedDictionary(); - - AutoObjectNames = new ConcurrentDictionary(); - // Note: This is not really correct, but with HLE of services, the only memory // region used that is used is Application, so we can use the other ones for anything. - KMemoryRegionManager region = MemoryRegions[(int)MemoryRegion.NvServices]; + KMemoryRegionManager region = KernelContext.MemoryRegions[(int)MemoryRegion.NvServices]; ulong hidPa = region.Address; ulong fontPa = region.Address + HidSize; @@ -214,11 +133,11 @@ namespace Ryujinx.HLE.HOS iirsPageList.AddRange(iirsPa, IirsSize / KMemoryManager.PageSize); timePageList.AddRange(timePa, TimeSize / KMemoryManager.PageSize); - HidSharedMem = new KSharedMemory(this, hidPageList, 0, 0, MemoryPermission.Read); - FontSharedMem = new KSharedMemory(this, fontPageList, 0, 0, MemoryPermission.Read); - IirsSharedMem = new KSharedMemory(this, iirsPageList, 0, 0, MemoryPermission.Read); + HidSharedMem = new KSharedMemory(KernelContext, hidPageList, 0, 0, MemoryPermission.Read); + FontSharedMem = new KSharedMemory(KernelContext, fontPageList, 0, 0, MemoryPermission.Read); + IirsSharedMem = new KSharedMemory(KernelContext, iirsPageList, 0, 0, MemoryPermission.Read); - KSharedMemory timeSharedMemory = new KSharedMemory(this, timePageList, 0, 0, MemoryPermission.Read); + KSharedMemory timeSharedMemory = new KSharedMemory(KernelContext, timePageList, 0, 0, MemoryPermission.Read); TimeServiceManager.Instance.Initialize(device, this, timeSharedMemory, timePa - DramMemoryMap.DramBase, TimeSize); @@ -230,9 +149,9 @@ namespace Ryujinx.HLE.HOS IUserInterface.InitializePort(this); - VsyncEvent = new KEvent(this); + VsyncEvent = new KEvent(KernelContext); - DisplayResolutionChangeEvent = new KEvent(this); + DisplayResolutionChangeEvent = new KEvent(KernelContext); ContentManager = contentManager; @@ -355,7 +274,7 @@ namespace Ryujinx.HLE.HOS { using (IStorage fs = new LocalStorage(kipFile, FileAccess.Read)) { - ProgramLoader.LoadKernelInitalProcess(this, new KipExecutable(fs)); + ProgramLoader.LoadKip(KernelContext, new KipExecutable(fs)); } } @@ -694,7 +613,7 @@ namespace Ryujinx.HLE.HOS ContentManager.LoadEntries(Device); - ProgramLoader.LoadStaticObjects(this, metaData, staticObjects.ToArray()); + ProgramLoader.LoadNsos(KernelContext, metaData, staticObjects.ToArray()); } public void LoadProgram(string filePath) @@ -791,7 +710,7 @@ namespace Ryujinx.HLE.HOS TitleId = metaData.Aci0.TitleId; TitleIs64Bit = metaData.Is64Bit; - ProgramLoader.LoadStaticObjects(this, metaData, new IExecutable[] { staticObject }); + ProgramLoader.LoadNsos(KernelContext, metaData, new IExecutable[] { staticObject }); } private Npdm GetDefaultNpdm() @@ -855,26 +774,11 @@ namespace Ryujinx.HLE.HOS VsyncEvent.ReadableEvent.Signal(); } - internal long GetThreadUid() - { - return Interlocked.Increment(ref _threadUid) - 1; - } - - internal long GetKipId() - { - return Interlocked.Increment(ref _kipId) - 1; - } - - internal long GetProcessId() - { - return Interlocked.Increment(ref _processId) - 1; - } - public void EnableMultiCoreScheduling() { if (!_hasStarted) { - Scheduler.MultiCoreScheduling = true; + KernelContext.Scheduler.MultiCoreScheduling = true; } } @@ -882,7 +786,7 @@ namespace Ryujinx.HLE.HOS { if (!_hasStarted) { - Scheduler.MultiCoreScheduling = false; + KernelContext.Scheduler.MultiCoreScheduling = false; } } @@ -901,25 +805,24 @@ namespace Ryujinx.HLE.HOS SurfaceFlinger.Dispose(); - KProcess terminationProcess = new KProcess(this); - - KThread terminationThread = new KThread(this); + KProcess terminationProcess = new KProcess(KernelContext); + KThread terminationThread = new KThread(KernelContext); terminationThread.Initialize(0, 0, 0, 3, 0, terminationProcess, ThreadType.Kernel, () => { // Force all threads to exit. - lock (Processes) + lock (KernelContext.Processes) { - foreach (KProcess process in Processes.Values) + foreach (KProcess process in KernelContext.Processes.Values) { process.Terminate(); } } // Exit ourself now! - Scheduler.ExitThread(terminationThread); - Scheduler.GetCurrentThread().Exit(); - Scheduler.RemoveThread(terminationThread); + KernelContext.Scheduler.ExitThread(terminationThread); + KernelContext.Scheduler.GetCurrentThread().Exit(); + KernelContext.Scheduler.RemoveThread(terminationThread); }); terminationThread.Start(); @@ -929,16 +832,14 @@ namespace Ryujinx.HLE.HOS INvDrvServices.Destroy(); // This is needed as the IPC Dummy KThread is also counted in the ThreadCounter. - ThreadCounter.Signal(); + KernelContext.ThreadCounter.Signal(); // It's only safe to release resources once all threads // have exited. - ThreadCounter.Signal(); - ThreadCounter.Wait(); + KernelContext.ThreadCounter.Signal(); + KernelContext.ThreadCounter.Wait(); - Scheduler.Dispose(); - - TimeManager.Dispose(); + KernelContext.Dispose(); Device.Unload(); } diff --git a/Ryujinx.HLE/HOS/Kernel/Common/KAutoObject.cs b/Ryujinx.HLE/HOS/Kernel/Common/KAutoObject.cs index 3b30dd808..812cbd304 100644 --- a/Ryujinx.HLE/HOS/Kernel/Common/KAutoObject.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/KAutoObject.cs @@ -4,20 +4,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Common { class KAutoObject { - protected Horizon System; + protected KernelContext KernelContext; private int _referenceCount; - public KAutoObject(Horizon system) + public KAutoObject(KernelContext context) { - System = system; + KernelContext = context; _referenceCount = 1; } public virtual KernelResult SetName(string name) { - if (!System.AutoObjectNames.TryAdd(name, this)) + if (!KernelContext.AutoObjectNames.TryAdd(name, this)) { return KernelResult.InvalidState; } @@ -25,9 +25,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Common return KernelResult.Success; } - public static KernelResult RemoveName(Horizon system, string name) + public static KernelResult RemoveName(KernelContext context, string name) { - if (!system.AutoObjectNames.TryRemove(name, out _)) + if (!context.AutoObjectNames.TryRemove(name, out _)) { return KernelResult.NotFound; } @@ -35,9 +35,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Common return KernelResult.Success; } - public static KAutoObject FindNamedObject(Horizon system, string name) + public static KAutoObject FindNamedObject(KernelContext context, string name) { - if (system.AutoObjectNames.TryGetValue(name, out KAutoObject obj)) + if (context.AutoObjectNames.TryGetValue(name, out KAutoObject obj)) { return obj; } diff --git a/Ryujinx.HLE/HOS/Kernel/Common/KResourceLimit.cs b/Ryujinx.HLE/HOS/Kernel/Common/KResourceLimit.cs index a7955d7ad..91501a988 100644 --- a/Ryujinx.HLE/HOS/Kernel/Common/KResourceLimit.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/KResourceLimit.cs @@ -8,17 +8,17 @@ namespace Ryujinx.HLE.HOS.Kernel.Common { private const int Time10SecondsMs = 10000; - private long[] _current; - private long[] _limit; - private long[] _available; + private readonly long[] _current; + private readonly long[] _limit; + private readonly long[] _available; - private object _lockObj; + private readonly object _lockObj; - private LinkedList _waitingThreads; + private readonly LinkedList _waitingThreads; private int _waitingThreadsCount; - public KResourceLimit(Horizon system) : base(system) + public KResourceLimit(KernelContext context) : base(context) { _current = new long[(int)LimitableResource.Count]; _limit = new long[(int)LimitableResource.Count]; @@ -57,7 +57,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common { _waitingThreadsCount++; - KConditionVariable.Wait(System, _waitingThreads, _lockObj, timeout); + KConditionVariable.Wait(KernelContext, _waitingThreads, _lockObj, timeout); _waitingThreadsCount--; @@ -101,7 +101,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common if (_waitingThreadsCount > 0) { - KConditionVariable.NotifyAll(System, _waitingThreads); + KConditionVariable.NotifyAll(KernelContext, _waitingThreads); } } } diff --git a/Ryujinx.HLE/HOS/Kernel/Common/KSynchronizationObject.cs b/Ryujinx.HLE/HOS/Kernel/Common/KSynchronizationObject.cs index 77d8fbff8..ddc0069d0 100644 --- a/Ryujinx.HLE/HOS/Kernel/Common/KSynchronizationObject.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/KSynchronizationObject.cs @@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common { public LinkedList WaitingThreads { get; } - public KSynchronizationObject(Horizon system) : base(system) + public KSynchronizationObject(KernelContext context) : base(context) { WaitingThreads = new LinkedList(); } @@ -24,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common public virtual void Signal() { - System.Synchronization.SignalObject(this); + KernelContext.Synchronization.SignalObject(this); } public virtual bool IsSignaled() diff --git a/Ryujinx.HLE/HOS/Kernel/Common/KernelTransfer.cs b/Ryujinx.HLE/HOS/Kernel/Common/KernelTransfer.cs index cd8d66612..8b739f66e 100644 --- a/Ryujinx.HLE/HOS/Kernel/Common/KernelTransfer.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/KernelTransfer.cs @@ -5,9 +5,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Common { static class KernelTransfer { - public static bool UserToKernelInt32(Horizon system, ulong address, out int value) + public static bool UserToKernelInt32(KernelContext context, ulong address, out int value) { - KProcess currentProcess = system.Scheduler.GetCurrentProcess(); + KProcess currentProcess = context.Scheduler.GetCurrentProcess(); if (currentProcess.CpuMemory.IsMapped(address) && currentProcess.CpuMemory.IsMapped(address + 3)) @@ -22,9 +22,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Common return false; } - public static bool UserToKernelInt32Array(Horizon system, ulong address, int[] values) + public static bool UserToKernelInt32Array(KernelContext context, ulong address, int[] values) { - KProcess currentProcess = system.Scheduler.GetCurrentProcess(); + KProcess currentProcess = context.Scheduler.GetCurrentProcess(); for (int index = 0; index < values.Length; index++, address += 4) { @@ -42,9 +42,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Common return true; } - public static bool UserToKernelString(Horizon system, ulong address, int size, out string value) + public static bool UserToKernelString(KernelContext context, ulong address, int size, out string value) { - KProcess currentProcess = system.Scheduler.GetCurrentProcess(); + KProcess currentProcess = context.Scheduler.GetCurrentProcess(); if (currentProcess.CpuMemory.IsMapped(address) && currentProcess.CpuMemory.IsMapped(address + (ulong)size - 1)) @@ -59,9 +59,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Common return false; } - public static bool KernelToUserInt32(Horizon system, ulong address, int value) + public static bool KernelToUserInt32(KernelContext context, ulong address, int value) { - KProcess currentProcess = system.Scheduler.GetCurrentProcess(); + KProcess currentProcess = context.Scheduler.GetCurrentProcess(); if (currentProcess.CpuMemory.IsMapped(address) && currentProcess.CpuMemory.IsMapped(address + 3)) @@ -74,9 +74,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Common return false; } - public static bool KernelToUserInt64(Horizon system, ulong address, long value) + public static bool KernelToUserInt64(KernelContext context, ulong address, long value) { - KProcess currentProcess = system.Scheduler.GetCurrentProcess(); + KProcess currentProcess = context.Scheduler.GetCurrentProcess(); if (currentProcess.CpuMemory.IsMapped(address) && currentProcess.CpuMemory.IsMapped(address + 7)) diff --git a/Ryujinx.HLE/HOS/Kernel/Ipc/KClientPort.cs b/Ryujinx.HLE/HOS/Kernel/Ipc/KClientPort.cs index 901b02223..9c542ca0a 100644 --- a/Ryujinx.HLE/HOS/Kernel/Ipc/KClientPort.cs +++ b/Ryujinx.HLE/HOS/Kernel/Ipc/KClientPort.cs @@ -8,19 +8,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc { private int _sessionsCount; private int _currentCapacity; - private int _maxSessions; + private readonly int _maxSessions; - private KPort _parent; + private readonly KPort _parent; public bool IsLight => _parent.IsLight; - private object _countIncLock; + private readonly object _countIncLock; // TODO: Remove that, we need it for now to allow HLE // SM implementation to work with the new IPC system. public IpcService Service { get; set; } - public KClientPort(Horizon system, KPort parent, int maxSessions) : base(system) + public KClientPort(KernelContext context, KPort parent, int maxSessions) : base(context) { _maxSessions = maxSessions; _parent = parent; @@ -32,7 +32,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc { clientSession = null; - KProcess currentProcess = System.Scheduler.GetCurrentProcess(); + KProcess currentProcess = KernelContext.Scheduler.GetCurrentProcess(); if (currentProcess.ResourceLimit != null && !currentProcess.ResourceLimit.Reserve(LimitableResource.Session, 1)) @@ -59,7 +59,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc } } - KSession session = new KSession(System); + KSession session = new KSession(KernelContext); if (Service != null) { @@ -85,7 +85,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc { clientSession = null; - KProcess currentProcess = System.Scheduler.GetCurrentProcess(); + KProcess currentProcess = KernelContext.Scheduler.GetCurrentProcess(); if (currentProcess.ResourceLimit != null && !currentProcess.ResourceLimit.Reserve(LimitableResource.Session, 1)) @@ -107,7 +107,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc } } - KLightSession session = new KLightSession(System); + KLightSession session = new KLightSession(KernelContext); KernelResult result = _parent.EnqueueIncomingLightSession(session.ServerSession); @@ -124,16 +124,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc return result; } - public new static KernelResult RemoveName(Horizon system, string name) + public new static KernelResult RemoveName(KernelContext context, string name) { - KAutoObject foundObj = FindNamedObject(system, name); + KAutoObject foundObj = FindNamedObject(context, name); if (!(foundObj is KClientPort)) { return KernelResult.NotFound; } - return KAutoObject.RemoveName(system, name); + return KAutoObject.RemoveName(context, name); } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/Ipc/KClientSession.cs b/Ryujinx.HLE/HOS/Kernel/Ipc/KClientSession.cs index a5109e96a..b99dd1cb9 100644 --- a/Ryujinx.HLE/HOS/Kernel/Ipc/KClientSession.cs +++ b/Ryujinx.HLE/HOS/Kernel/Ipc/KClientSession.cs @@ -17,31 +17,31 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc // services implementation to work with the new IPC system. public IpcService Service { get; set; } - public KClientSession(Horizon system, KSession parent) : base(system) + public KClientSession(KernelContext context, KSession parent) : base(context) { _parent = parent; State = ChannelState.Open; - CreatorProcess = system.Scheduler.GetCurrentProcess(); + CreatorProcess = context.Scheduler.GetCurrentProcess(); CreatorProcess.IncrementReferenceCount(); } public KernelResult SendSyncRequest(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0) { - KThread currentThread = System.Scheduler.GetCurrentThread(); + KThread currentThread = KernelContext.Scheduler.GetCurrentThread(); KSessionRequest request = new KSessionRequest(currentThread, customCmdBuffAddr, customCmdBuffSize); - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); currentThread.SignaledObj = null; currentThread.ObjSyncResult = KernelResult.Success; KernelResult result = _parent.ServerSession.EnqueueRequest(request); - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); if (result == KernelResult.Success) { diff --git a/Ryujinx.HLE/HOS/Kernel/Ipc/KLightClientSession.cs b/Ryujinx.HLE/HOS/Kernel/Ipc/KLightClientSession.cs index 62c352bfe..27a9732be 100644 --- a/Ryujinx.HLE/HOS/Kernel/Ipc/KLightClientSession.cs +++ b/Ryujinx.HLE/HOS/Kernel/Ipc/KLightClientSession.cs @@ -4,9 +4,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc { class KLightClientSession : KAutoObject { - private KLightSession _parent; + private readonly KLightSession _parent; - public KLightClientSession(Horizon system, KLightSession parent) : base(system) + public KLightClientSession(KernelContext context, KLightSession parent) : base(context) { _parent = parent; } diff --git a/Ryujinx.HLE/HOS/Kernel/Ipc/KLightServerSession.cs b/Ryujinx.HLE/HOS/Kernel/Ipc/KLightServerSession.cs index 1ea2205d0..0edbba6cb 100644 --- a/Ryujinx.HLE/HOS/Kernel/Ipc/KLightServerSession.cs +++ b/Ryujinx.HLE/HOS/Kernel/Ipc/KLightServerSession.cs @@ -4,9 +4,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc { class KLightServerSession : KAutoObject { - private KLightSession _parent; + private readonly KLightSession _parent; - public KLightServerSession(Horizon system, KLightSession parent) : base(system) + public KLightServerSession(KernelContext context, KLightSession parent) : base(context) { _parent = parent; } diff --git a/Ryujinx.HLE/HOS/Kernel/Ipc/KLightSession.cs b/Ryujinx.HLE/HOS/Kernel/Ipc/KLightSession.cs index 166de065e..3abb1ab0d 100644 --- a/Ryujinx.HLE/HOS/Kernel/Ipc/KLightSession.cs +++ b/Ryujinx.HLE/HOS/Kernel/Ipc/KLightSession.cs @@ -7,10 +7,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc public KLightServerSession ServerSession { get; } public KLightClientSession ClientSession { get; } - public KLightSession(Horizon system) : base(system) + public KLightSession(KernelContext context) : base(context) { - ServerSession = new KLightServerSession(system, this); - ClientSession = new KLightClientSession(system, this); + ServerSession = new KLightServerSession(context, this); + ClientSession = new KLightClientSession(context, this); } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/Ipc/KPort.cs b/Ryujinx.HLE/HOS/Kernel/Ipc/KPort.cs index 9d93cf7b9..2f67aeaec 100644 --- a/Ryujinx.HLE/HOS/Kernel/Ipc/KPort.cs +++ b/Ryujinx.HLE/HOS/Kernel/Ipc/KPort.cs @@ -13,10 +13,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc public bool IsLight { get; private set; } - public KPort(Horizon system, int maxSessions, bool isLight, long nameAddress) : base(system) + public KPort(KernelContext context, int maxSessions, bool isLight, long nameAddress) : base(context) { - ServerPort = new KServerPort(system, this); - ClientPort = new KClientPort(system, this, maxSessions); + ServerPort = new KServerPort(context, this); + ClientPort = new KClientPort(context, this, maxSessions); IsLight = isLight; _nameAddress = nameAddress; @@ -28,7 +28,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc { KernelResult result; - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if (_state == ChannelState.Open) { @@ -41,7 +41,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc result = KernelResult.PortClosed; } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return result; } @@ -50,7 +50,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc { KernelResult result; - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if (_state == ChannelState.Open) { @@ -63,7 +63,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc result = KernelResult.PortClosed; } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return result; } diff --git a/Ryujinx.HLE/HOS/Kernel/Ipc/KServerPort.cs b/Ryujinx.HLE/HOS/Kernel/Ipc/KServerPort.cs index 919df357b..21a3919cf 100644 --- a/Ryujinx.HLE/HOS/Kernel/Ipc/KServerPort.cs +++ b/Ryujinx.HLE/HOS/Kernel/Ipc/KServerPort.cs @@ -5,14 +5,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc { class KServerPort : KSynchronizationObject { - private LinkedList _incomingConnections; - private LinkedList _lightIncomingConnections; + private readonly LinkedList _incomingConnections; + private readonly LinkedList _lightIncomingConnections; - private KPort _parent; + private readonly KPort _parent; public bool IsLight => _parent.IsLight; - public KServerPort(Horizon system, KPort parent) : base(system) + public KServerPort(KernelContext context, KPort parent) : base(context) { _parent = parent; @@ -32,7 +32,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc private void AcceptIncomingConnection(LinkedList list, T session) { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); list.AddLast(session); @@ -41,7 +41,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc Signal(); } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); } public KServerSession AcceptIncomingConnection() @@ -56,9 +56,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc private T AcceptIncomingConnection(LinkedList list) { - T session = default(T); + T session = default; - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if (list.Count != 0) { @@ -67,7 +67,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc list.RemoveFirst(); } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return session; } diff --git a/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs b/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs index 201b0bec1..70b54d054 100644 --- a/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs +++ b/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs @@ -177,7 +177,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc private KSessionRequest _activeRequest; - public KServerSession(Horizon system, KSession parent) : base(system) + public KServerSession(KernelContext context, KSession parent) : base(context) { _parent = parent; @@ -214,28 +214,28 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc public KernelResult Receive(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0) { - KThread serverThread = System.Scheduler.GetCurrentThread(); + KThread serverThread = KernelContext.Scheduler.GetCurrentThread(); KProcess serverProcess = serverThread.Owner; - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if (_parent.ClientSession.State != ChannelState.Open) { - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return KernelResult.PortRemoteClosed; } if (_activeRequest != null || !DequeueRequest(out KSessionRequest request)) { - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return KernelResult.NotFound; } if (request.ClientThread == null) { - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return KernelResult.PortRemoteClosed; } @@ -243,7 +243,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc KThread clientThread = request.ClientThread; KProcess clientProcess = clientThread.Owner; - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); _activeRequest = request; @@ -267,7 +267,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc CloseAllHandles(serverMsg, clientHeader, serverProcess); - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); _activeRequest = null; @@ -276,7 +276,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc Signal(); } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); WakeClientThread(request, clientResult); } @@ -351,8 +351,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc for (int index = 0; index < clientHeader.CopyHandlesCount; index++) { int newHandle = 0; - - int handle = System.Device.Memory.Read(clientMsg.DramAddress + offset * 4); + int handle = KernelContext.Memory.Read(clientMsg.DramAddress + offset * 4); if (clientResult == KernelResult.Success && handle != 0) { @@ -367,8 +366,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc for (int index = 0; index < clientHeader.MoveHandlesCount; index++) { int newHandle = 0; - - int handle = System.Device.Memory.Read(clientMsg.DramAddress + offset * 4); + int handle = KernelContext.Memory.Read(clientMsg.DramAddress + offset * 4); if (handle != 0) { @@ -404,7 +402,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc for (int index = 0; index < clientHeader.PointerBuffersCount; index++) { - ulong pointerDesc = System.Device.Memory.Read(clientMsg.DramAddress + offset * 4); + ulong pointerDesc = KernelContext.Memory.Read(clientMsg.DramAddress + offset * 4); PointerBufferDesc descriptor = new PointerBufferDesc(pointerDesc); @@ -465,9 +463,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc { ulong clientDescAddress = clientMsg.DramAddress + offset * 4; - uint descWord0 = System.Device.Memory.Read(clientDescAddress + 0); - uint descWord1 = System.Device.Memory.Read(clientDescAddress + 4); - uint descWord2 = System.Device.Memory.Read(clientDescAddress + 8); + uint descWord0 = KernelContext.Memory.Read(clientDescAddress + 0); + uint descWord1 = KernelContext.Memory.Read(clientDescAddress + 4); + uint descWord2 = KernelContext.Memory.Read(clientDescAddress + 8); bool isSendDesc = index < clientHeader.SendBuffersCount; bool isExchangeDesc = index >= clientHeader.SendBuffersCount + clientHeader.ReceiveBuffersCount; @@ -580,7 +578,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc copySrc = clientProcess.MemoryManager.GetDramAddressFromVa(copySrc); copyDst = serverProcess.MemoryManager.GetDramAddressFromVa(copyDst); - System.Device.Memory.Copy(copyDst, copySrc, copySize); + KernelContext.Memory.Copy(copyDst, copySrc, copySize); } if (clientResult != KernelResult.Success) @@ -596,14 +594,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc public KernelResult Reply(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0) { - KThread serverThread = System.Scheduler.GetCurrentThread(); + KThread serverThread = KernelContext.Scheduler.GetCurrentThread(); KProcess serverProcess = serverThread.Owner; - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if (_activeRequest == null) { - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return KernelResult.InvalidState; } @@ -617,7 +615,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc Signal(); } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); KThread clientThread = request.ClientThread; KProcess clientProcess = clientThread.Owner; @@ -700,8 +698,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc } // Copy header. - System.Device.Memory.Write(clientMsg.DramAddress + 0, serverHeader.Word0); - System.Device.Memory.Write(clientMsg.DramAddress + 4, serverHeader.Word1); + KernelContext.Memory.Write(clientMsg.DramAddress + 0, serverHeader.Word0); + KernelContext.Memory.Write(clientMsg.DramAddress + 4, serverHeader.Word1); // Copy handles. uint offset; @@ -710,11 +708,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc { offset = 3; - System.Device.Memory.Write(clientMsg.DramAddress + 8, serverHeader.Word2); + KernelContext.Memory.Write(clientMsg.DramAddress + 8, serverHeader.Word2); if (serverHeader.HasPid) { - System.Device.Memory.Write(clientMsg.DramAddress + offset * 4, serverProcess.Pid); + KernelContext.Memory.Write(clientMsg.DramAddress + offset * 4, serverProcess.Pid); offset += 2; } @@ -730,7 +728,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc GetCopyObjectHandle(serverThread, clientProcess, handle, out newHandle); } - System.Device.Memory.Write(clientMsg.DramAddress + offset * 4, newHandle); + KernelContext.Memory.Write(clientMsg.DramAddress + offset * 4, newHandle); offset++; } @@ -753,7 +751,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc } } - System.Device.Memory.Write(clientMsg.DramAddress + offset * 4, newHandle); + KernelContext.Memory.Write(clientMsg.DramAddress + offset * 4, newHandle); offset++; } @@ -821,9 +819,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc { ulong dstDescAddress = clientMsg.DramAddress + offset * 4; - System.Device.Memory.Write(dstDescAddress + 0, 0); - System.Device.Memory.Write(dstDescAddress + 4, 0); - System.Device.Memory.Write(dstDescAddress + 8, 0); + KernelContext.Memory.Write(dstDescAddress + 0, 0); + KernelContext.Memory.Write(dstDescAddress + 4, 0); + KernelContext.Memory.Write(dstDescAddress + 8, 0); offset += 3; } @@ -857,7 +855,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc copyDst = clientProcess.MemoryManager.GetDramAddressFromVa(copyDst); copySrc = serverProcess.MemoryManager.GetDramAddressFromVa(copySrc); - System.Device.Memory.Copy(copyDst, copySrc, copySize); + KernelContext.Memory.Copy(copyDst, copySrc, copySize); } } @@ -878,16 +876,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc private MessageHeader GetClientMessageHeader(Message clientMsg) { - uint word0 = System.Device.Memory.Read(clientMsg.DramAddress + 0); - uint word1 = System.Device.Memory.Read(clientMsg.DramAddress + 4); - uint word2 = System.Device.Memory.Read(clientMsg.DramAddress + 8); + uint word0 = KernelContext.Memory.Read(clientMsg.DramAddress + 0); + uint word1 = KernelContext.Memory.Read(clientMsg.DramAddress + 4); + uint word2 = KernelContext.Memory.Read(clientMsg.DramAddress + 8); return new MessageHeader(word0, word1, word2); } private MessageHeader GetServerMessageHeader(Message serverMsg) { - KProcess currentProcess = System.Scheduler.GetCurrentProcess(); + KProcess currentProcess = KernelContext.Scheduler.GetCurrentProcess(); uint word0 = currentProcess.CpuMemory.Read(serverMsg.Address + 0); uint word1 = currentProcess.CpuMemory.Read(serverMsg.Address + 4); @@ -974,7 +972,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc for (int index = 0; index < recvListSize; index++) { - receiveList[index] = System.Device.Memory.Read(recvListAddress + (ulong)index * 8); + receiveList[index] = KernelContext.Memory.Read(recvListAddress + (ulong)index * 8); } return receiveList; @@ -1139,7 +1137,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc private IEnumerable IterateWithRemovalOfAllRequests() { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if (_activeRequest != null) { @@ -1147,13 +1145,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc _activeRequest = null; - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); yield return request; } else { - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); } while (DequeueRequest(out KSessionRequest request)) @@ -1166,7 +1164,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc { request = null; - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); bool hasRequest = _requests.First != null; @@ -1177,7 +1175,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc _requests.RemoveFirst(); } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return hasRequest; } @@ -1211,11 +1209,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc } else { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); WakeAndSetResult(request.ClientThread, result); - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); } } @@ -1225,8 +1223,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc ulong address = clientProcess.MemoryManager.GetDramAddressFromVa(request.CustomCmdBuffAddr); - System.Device.Memory.Write(address, 0); - System.Device.Memory.Write(address + 8, (int)result); + KernelContext.Memory.Write(address, 0); + KernelContext.Memory.Write(address + 8, (int)result); clientProcess.MemoryManager.UnborrowIpcBuffer( request.CustomCmdBuffAddr, @@ -1238,14 +1236,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc private void WakeServerThreads(KernelResult result) { // Wake all server threads waiting for requests. - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); foreach (KThread thread in WaitingThreads) { WakeAndSetResult(thread, result); } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); } private void WakeAndSetResult(KThread thread, KernelResult result) diff --git a/Ryujinx.HLE/HOS/Kernel/Ipc/KSession.cs b/Ryujinx.HLE/HOS/Kernel/Ipc/KSession.cs index cbf689a57..25e6eee57 100644 --- a/Ryujinx.HLE/HOS/Kernel/Ipc/KSession.cs +++ b/Ryujinx.HLE/HOS/Kernel/Ipc/KSession.cs @@ -11,10 +11,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc private bool _hasBeenInitialized; - public KSession(Horizon system) : base(system) + public KSession(KernelContext context) : base(context) { - ServerSession = new KServerSession(system, this); - ClientSession = new KClientSession(system, this); + ServerSession = new KServerSession(context, this); + ClientSession = new KClientSession(context, this); _hasBeenInitialized = true; } diff --git a/Ryujinx.HLE/HOS/Kernel/KernelConstants.cs b/Ryujinx.HLE/HOS/Kernel/KernelConstants.cs new file mode 100644 index 000000000..4b5d3a324 --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/KernelConstants.cs @@ -0,0 +1,16 @@ +using Ryujinx.HLE.HOS.Kernel.Memory; + +namespace Ryujinx.HLE.HOS.Kernel +{ + static class KernelConstants + { + public const int InitialKipId = 1; + public const int InitialProcessId = 0x51; + + public const int MemoryBlockAllocatorSize = 0x2710; + + public const ulong UserSlabHeapBase = DramMemoryMap.SlabHeapBase; + public const ulong UserSlabHeapItemSize = KMemoryManager.PageSize; + public const ulong UserSlabHeapSize = 0x3de000; + } +} diff --git a/Ryujinx.HLE/HOS/Kernel/KernelContext.cs b/Ryujinx.HLE/HOS/Kernel/KernelContext.cs new file mode 100644 index 000000000..feb3f9e9b --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/KernelContext.cs @@ -0,0 +1,114 @@ +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Memory; +using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.HLE.HOS.Kernel.SupervisorCall; +using Ryujinx.HLE.HOS.Kernel.Threading; +using Ryujinx.Memory; +using System; +using System.Collections.Concurrent; +using System.Threading; + +namespace Ryujinx.HLE.HOS.Kernel +{ + class KernelContext : IDisposable + { + public long PrivilegedProcessLowestId { get; set; } = 1; + public long PrivilegedProcessHighestId { get; set; } = 8; + + public bool EnableVersionChecks { get; set; } + + public bool KernelInitialized { get; } + + public Switch Device { get; } + public MemoryBlock Memory { get; } + public Syscall Syscall { get; } + public SyscallHandler SyscallHandler { get; } + + public CountdownEvent ThreadCounter { get; } + + public KResourceLimit ResourceLimit { get; } + + public KMemoryRegionManager[] MemoryRegions { get; } + + public KMemoryBlockAllocator LargeMemoryBlockAllocator { get; } + public KMemoryBlockAllocator SmallMemoryBlockAllocator { get; } + + public KSlabHeap UserSlabHeapPages { get; } + + public KCriticalSection CriticalSection { get; } + public KScheduler Scheduler { get; } + public KTimeManager TimeManager { get; } + public KSynchronization Synchronization { get; } + public KContextIdManager ContextIdManager { get; } + + public ConcurrentDictionary Processes { get; } + public ConcurrentDictionary AutoObjectNames { get; } + + private long _kipId; + private long _processId; + private long _threadUid; + + public KernelContext(Switch device, MemoryBlock memory) + { + Device = device; + Memory = memory; + + Syscall = new Syscall(device, this); + + SyscallHandler = new SyscallHandler(this); + + ThreadCounter = new CountdownEvent(1); + + ResourceLimit = new KResourceLimit(this); + + KernelInit.InitializeResourceLimit(ResourceLimit); + + MemoryRegions = KernelInit.GetMemoryRegions(); + + LargeMemoryBlockAllocator = new KMemoryBlockAllocator(KernelConstants.MemoryBlockAllocatorSize * 2); + SmallMemoryBlockAllocator = new KMemoryBlockAllocator(KernelConstants.MemoryBlockAllocatorSize); + + UserSlabHeapPages = new KSlabHeap( + KernelConstants.UserSlabHeapBase, + KernelConstants.UserSlabHeapItemSize, + KernelConstants.UserSlabHeapSize); + + CriticalSection = new KCriticalSection(this); + Scheduler = new KScheduler(this); + TimeManager = new KTimeManager(); + Synchronization = new KSynchronization(this); + ContextIdManager = new KContextIdManager(); + + Scheduler.StartAutoPreemptionThread(); + + KernelInitialized = true; + + Processes = new ConcurrentDictionary(); + AutoObjectNames = new ConcurrentDictionary(); + + _kipId = KernelConstants.InitialKipId; + _processId = KernelConstants.InitialProcessId; + } + + public long NewThreadUid() + { + return Interlocked.Increment(ref _threadUid) - 1; + } + + public long NewKipId() + { + return Interlocked.Increment(ref _kipId) - 1; + } + + public long NewProcessId() + { + return Interlocked.Increment(ref _processId) - 1; + } + + public void Dispose() + { + Scheduler.Dispose(); + TimeManager.Dispose(); + } + } +} diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs index 9dcacd307..77f190c43 100644 --- a/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs @@ -31,7 +31,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory private MemoryManager _cpuMemory; - private Horizon _system; + private KernelContext _context; public ulong AddrSpaceStart { get; private set; } public ulong AddrSpaceEnd { get; private set; } @@ -73,9 +73,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory private MersenneTwister _randomNumberGenerator; - public KMemoryManager(Horizon system, MemoryManager cpuMemory) + public KMemoryManager(KernelContext context, MemoryManager cpuMemory) { - _system = system; + _context = context; _cpuMemory = cpuMemory; _blocks = new LinkedList(); @@ -99,7 +99,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory throw new ArgumentException(nameof(addrSpaceType)); } - _contextId = _system.ContextIdManager.GetId(); + _contextId = _context.ContextIdManager.GetId(); ulong addrSpaceBase = 0; ulong addrSpaceSize = 1UL << AddrSpaceSizes[(int)addrSpaceType]; @@ -117,7 +117,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory if (result != KernelResult.Success) { - _system.ContextIdManager.PutId(_contextId); + _context.ContextIdManager.PutId(_contextId); } return result; @@ -727,7 +727,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory return KernelResult.OutOfMemory; } - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); ulong currentHeapSize = GetHeapSize(); @@ -1303,7 +1303,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory ulong remainingPages = remainingSize / PageSize; - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); if (currentProcess.ResourceLimit != null && !currentProcess.ResourceLimit.Reserve(LimitableResource.Memory, remainingSize)) @@ -1433,7 +1433,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory PhysicalMemoryUsage -= heapMappedSize; - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); currentProcess.ResourceLimit?.Release(LimitableResource.Memory, heapMappedSize); @@ -1582,17 +1582,17 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory attributeMask | MemoryAttribute.Uncached, attributeExpected)) { - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); serverAddress = currentProcess.MemoryManager.GetDramAddressFromVa(serverAddress); if (toServer) { - _system.Device.Memory.Copy(serverAddress, GetDramAddressFromVa(clientAddress), size); + _context.Memory.Copy(serverAddress, GetDramAddressFromVa(clientAddress), size); } else { - _system.Device.Memory.Copy(GetDramAddressFromVa(clientAddress), serverAddress, size); + _context.Memory.Copy(GetDramAddressFromVa(clientAddress), serverAddress, size); } return KernelResult.Success; @@ -1843,11 +1843,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory { ulong unusedSizeBefore = address - addressTruncated; - _system.Device.Memory.ZeroFill(dstFirstPagePa, unusedSizeBefore); + _context.Memory.ZeroFill(dstFirstPagePa, unusedSizeBefore); ulong copySize = addressRounded <= endAddr ? addressRounded - address : size; - _system.Device.Memory.Copy( + _context.Memory.Copy( GetDramAddressFromPa(dstFirstPagePa + unusedSizeBefore), GetDramAddressFromPa(srcFirstPagePa + unusedSizeBefore), copySize); @@ -1862,7 +1862,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory if (unusedSizeAfter != 0) { - _system.Device.Memory.ZeroFill(firstPageFillAddress, unusedSizeAfter); + _context.Memory.ZeroFill(firstPageFillAddress, unusedSizeAfter); } KPageList pages = new KPageList(); @@ -1909,7 +1909,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory { ulong copySize = endAddr - endAddrTruncated; - _system.Device.Memory.Copy( + _context.Memory.Copy( GetDramAddressFromPa(dstLastPagePa), GetDramAddressFromPa(srcLastPagePa), copySize); @@ -1922,7 +1922,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory unusedSizeAfter = PageSize; } - _system.Device.Memory.ZeroFill(lastPageFillAddr, unusedSizeAfter); + _context.Memory.ZeroFill(lastPageFillAddr, unusedSizeAfter); if (pages.AddRange(dstFirstPagePa, 1) != KernelResult.Success) { @@ -1939,14 +1939,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory private ulong AllocateSinglePage(MemoryRegion region, bool aslrDisabled) { - KMemoryRegionManager regionMgr = _system.MemoryRegions[(int)region]; + KMemoryRegionManager regionMgr = _context.MemoryRegions[(int)region]; return regionMgr.AllocatePagesContiguous(1, aslrDisabled); } private void FreeSinglePage(MemoryRegion region, ulong address) { - KMemoryRegionManager regionMgr = _system.MemoryRegions[(int)region]; + KMemoryRegionManager regionMgr = _context.MemoryRegions[(int)region]; regionMgr.FreePage(address); } @@ -3099,7 +3099,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory private KMemoryRegionManager GetMemoryRegionManager() { - return _system.MemoryRegions[(int)_memRegion]; + return _context.MemoryRegions[(int)_memRegion]; } private KernelResult MmuMapPages(ulong address, KPageList pageList) diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/KSharedMemory.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KSharedMemory.cs index 6b92ed30a..65134f0d5 100644 --- a/Ryujinx.HLE/HOS/Kernel/Memory/KSharedMemory.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KSharedMemory.cs @@ -6,19 +6,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory { class KSharedMemory : KAutoObject { - private KPageList _pageList; + private readonly KPageList _pageList; - private long _ownerPid; + private readonly long _ownerPid; - private MemoryPermission _ownerPermission; - private MemoryPermission _userPermission; + private readonly MemoryPermission _ownerPermission; + private readonly MemoryPermission _userPermission; public KSharedMemory( - Horizon system, + KernelContext context, KPageList pageList, long ownerPid, MemoryPermission ownerPermission, - MemoryPermission userPermission) : base(system) + MemoryPermission userPermission) : base(context) { _pageList = pageList; _ownerPid = ownerPid; diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/KTransferMemory.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KTransferMemory.cs index a0929eca0..6da0c4056 100644 --- a/Ryujinx.HLE/HOS/Kernel/Memory/KTransferMemory.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KTransferMemory.cs @@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory public ulong Address { get; private set; } public ulong Size { get; private set; } - public KTransferMemory(Horizon system, ulong address, ulong size) : base(system) + public KTransferMemory(KernelContext context, ulong address, ulong size) : base(context) { Address = address; Size = size; diff --git a/Ryujinx.HLE/HOS/Kernel/Process/KHandleTable.cs b/Ryujinx.HLE/HOS/Kernel/Process/KHandleTable.cs index e9dd14b2e..b733501a7 100644 --- a/Ryujinx.HLE/HOS/Kernel/Process/KHandleTable.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KHandleTable.cs @@ -9,7 +9,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process public const int SelfThreadHandle = (0x1ffff << 15) | 0; public const int SelfProcessHandle = (0x1ffff << 15) | 1; - private Horizon _system; + private readonly KernelContext _context; private KHandleEntry[] _table; @@ -22,9 +22,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process private ushort _idCounter; - public KHandleTable(Horizon system) + public KHandleTable(KernelContext context) { - _system = system; + _context = context; } public KernelResult Initialize(int size) @@ -136,8 +136,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process public void CancelHandleReservation(int handle) { - int index = (handle >> 0) & 0x7fff; - int handleId = (handle >> 15); + int index = (handle >> 0) & 0x7fff; lock (_table) { @@ -162,7 +161,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process KHandleEntry entry = _table[index]; entry.Obj = obj; - entry.HandleId = (ushort)(handle >> 15); + entry.HandleId = (ushort)handleId; obj.IncrementReferenceCount(); } @@ -230,14 +229,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process } } - return default(T); + return default; } public KThread GetKThread(int handle) { if (handle == SelfThreadHandle) { - return _system.Scheduler.GetCurrentThread(); + return _context.Scheduler.GetCurrentThread(); } else { @@ -249,7 +248,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { if (handle == SelfProcessHandle) { - return _system.Scheduler.GetCurrentProcess(); + return _context.Scheduler.GetCurrentProcess(); } else { diff --git a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs index c7d111306..81f8bb6a6 100644 --- a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -4,7 +4,6 @@ using Ryujinx.Cpu; using Ryujinx.HLE.Exceptions; using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Memory; -using Ryujinx.HLE.HOS.Kernel.SupervisorCall; using Ryujinx.HLE.HOS.Kernel.Threading; using System; using System.Collections.Generic; @@ -80,20 +79,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process public MemoryManager CpuMemory { get; private set; } public CpuContext CpuContext { get; private set; } - private SvcHandler _svcHandler; - - private Horizon _system; - public HleProcessDebugger Debugger { get; private set; } - public KProcess(Horizon system) : base(system) + public KProcess(KernelContext context) : base(context) { _processLock = new object(); _threadingLock = new object(); - _system = system; - - AddressArbiter = new KAddressArbiter(system); + AddressArbiter = new KAddressArbiter(context); _fullTlsPages = new SortedDictionary(); _freeTlsPages = new SortedDictionary(); @@ -104,8 +97,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process _threads = new LinkedList(); - _svcHandler = new SvcHandler(system.Device, this); - Debugger = new HleProcessDebugger(this); } @@ -130,8 +121,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process ulong codeSize = (ulong)creationInfo.CodePagesCount * KMemoryManager.PageSize; KMemoryBlockAllocator memoryBlockAllocator = (MmuFlags & 0x40) != 0 - ? System.LargeMemoryBlockAllocator - : System.SmallMemoryBlockAllocator; + ? KernelContext.LargeMemoryBlockAllocator + : KernelContext.SmallMemoryBlockAllocator; KernelResult result = MemoryManager.InitializeForProcess( addrSpaceType, @@ -170,9 +161,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process return result; } - Pid = System.GetKipId(); + Pid = KernelContext.NewKipId(); - if (Pid == 0 || (ulong)Pid >= Horizon.InitialProcessId) + if (Pid == 0 || (ulong)Pid >= KernelConstants.InitialProcessId) { throw new InvalidOperationException($"Invalid KIP Id {Pid}."); } @@ -224,8 +215,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process else { memoryBlockAllocator = (MmuFlags & 0x40) != 0 - ? System.LargeMemoryBlockAllocator - : System.SmallMemoryBlockAllocator; + ? KernelContext.LargeMemoryBlockAllocator + : KernelContext.SmallMemoryBlockAllocator; } AddressSpaceType addrSpaceType = (AddressSpaceType)((creationInfo.MmuFlags >> 1) & 7); @@ -283,9 +274,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process return result; } - Pid = System.GetProcessId(); + Pid = KernelContext.NewProcessId(); - if (Pid == -1 || (ulong)Pid < Horizon.InitialProcessId) + if (Pid == -1 || (ulong)Pid < KernelConstants.InitialProcessId) { throw new InvalidOperationException($"Invalid Process Id {Pid}."); } @@ -350,7 +341,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process uint requiredKernelVersionMajor = (uint)Capabilities.KernelReleaseVersion >> 19; uint requiredKernelVersionMinor = ((uint)Capabilities.KernelReleaseVersion >> 15) & 0xf; - if (System.EnableVersionChecks) + if (KernelContext.EnableVersionChecks) { if (requiredKernelVersionMajor > KernelVersionMajor) { @@ -419,7 +410,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process public KernelResult AllocateThreadLocalStorage(out ulong address) { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); KernelResult result; @@ -462,16 +453,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Process } } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return result; } private KernelResult AllocateTlsPage(out KTlsPageInfo pageInfo) { - pageInfo = default(KTlsPageInfo); + pageInfo = default; - if (!System.UserSlabHeapPages.TryGetItem(out ulong tlsPagePa)) + if (!KernelContext.UserSlabHeapPages.TryGetItem(out ulong tlsPagePa)) { return KernelResult.OutOfMemory; } @@ -494,7 +485,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process if (result != KernelResult.Success) { - System.UserSlabHeapPages.Free(tlsPagePa); + KernelContext.UserSlabHeapPages.Free(tlsPagePa); } else { @@ -510,7 +501,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { ulong tlsPageAddr = BitUtils.AlignDown(tlsSlotAddr, KMemoryManager.PageSize); - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); KernelResult result = KernelResult.Success; @@ -538,7 +529,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process // from all trees, and free the memory it was using. _freeTlsPages.Remove(tlsPageAddr); - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); FreeTlsPage(pageInfo); @@ -546,7 +537,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process } } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return result; } @@ -562,7 +553,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process if (result == KernelResult.Success) { - System.UserSlabHeapPages.Free(tlsPagePa); + KernelContext.UserSlabHeapPages.Free(tlsPagePa); } return result; @@ -692,7 +683,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process return result; } - HandleTable = new KHandleTable(System); + HandleTable = new KHandleTable(KernelContext); result = HandleTable.Initialize(Capabilities.HandleTableSize); @@ -703,7 +694,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process return result; } - mainThread = new KThread(System); + mainThread = new KThread(KernelContext); result = mainThread.Initialize( _entrypoint, @@ -792,25 +783,25 @@ namespace Ryujinx.HLE.HOS.Kernel.Process public void SubscribeThreadEventHandlers(ARMeilleure.State.ExecutionContext context) { context.Interrupt += InterruptHandler; - context.SupervisorCall += _svcHandler.SvcCall; + context.SupervisorCall += KernelContext.SyscallHandler.SvcCall; context.Undefined += UndefinedInstructionHandler; } private void InterruptHandler(object sender, EventArgs e) { - System.Scheduler.ContextSwitch(); + KernelContext.Scheduler.ContextSwitch(); } public void IncrementThreadCount() { Interlocked.Increment(ref _threadCount); - System.ThreadCounter.AddCount(); + KernelContext.ThreadCounter.AddCount(); } public void DecrementThreadCountAndTerminateIfZero() { - System.ThreadCounter.Signal(); + KernelContext.ThreadCounter.Signal(); if (Interlocked.Decrement(ref _threadCount) == 0) { @@ -820,7 +811,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process public void DecrementToZeroWhileTerminatingCurrent() { - System.ThreadCounter.Signal(); + KernelContext.ThreadCounter.Signal(); while (Interlocked.Decrement(ref _threadCount) != 0) { @@ -917,7 +908,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process bool shallTerminate = false; - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); lock (_processLock) { @@ -941,11 +932,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Process } } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); if (shallTerminate) { - UnpauseAndTerminateAllThreadsExcept(System.Scheduler.GetCurrentThread()); + UnpauseAndTerminateAllThreadsExcept(KernelContext.Scheduler.GetCurrentThread()); HandleTable.Destroy(); @@ -960,7 +951,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { bool shallTerminate = false; - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); lock (_processLock) { @@ -977,11 +968,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Process } } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); if (shallTerminate) { - UnpauseAndTerminateAllThreadsExcept(System.Scheduler.GetCurrentThread()); + UnpauseAndTerminateAllThreadsExcept(KernelContext.Scheduler.GetCurrentThread()); HandleTable.Destroy(); @@ -995,7 +986,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { lock (_threadingLock) { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); foreach (KThread thread in _threads) { @@ -1005,7 +996,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process } } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); } KThread blockedThread = null; @@ -1048,18 +1039,18 @@ namespace Ryujinx.HLE.HOS.Kernel.Process ResourceLimit.Release(LimitableResource.Memory, GetMemoryUsage()); } - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); SetState(ProcessState.Exited); - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); } public KernelResult ClearIfNotExited() { KernelResult result; - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); lock (_processLock) { @@ -1075,7 +1066,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process } } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return result; } @@ -1086,40 +1077,36 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { foreach (KThread thread in _threads) { - System.Scheduler.ExitThread(thread); - - System.Scheduler.CoreManager.Set(thread.HostThread); + KernelContext.Scheduler.ExitThread(thread); + KernelContext.Scheduler.CoreManager.Set(thread.HostThread); } } } private void InitializeMemoryManager(AddressSpaceType addrSpaceType, MemoryRegion memRegion) { - int addrSpaceBits; - - switch (addrSpaceType) + int addrSpaceBits = addrSpaceType switch { - case AddressSpaceType.Addr32Bits: addrSpaceBits = 32; break; - case AddressSpaceType.Addr36Bits: addrSpaceBits = 36; break; - case AddressSpaceType.Addr32BitsNoMap: addrSpaceBits = 32; break; - case AddressSpaceType.Addr39Bits: addrSpaceBits = 39; break; + AddressSpaceType.Addr32Bits => 32, + AddressSpaceType.Addr36Bits => 36, + AddressSpaceType.Addr32BitsNoMap => 32, + AddressSpaceType.Addr39Bits => 39, + _ => throw new ArgumentException(nameof(addrSpaceType)) + }; - default: throw new ArgumentException(nameof(addrSpaceType)); - } - - CpuMemory = new MemoryManager(_system.Device.Memory, 1UL << addrSpaceBits); + CpuMemory = new MemoryManager(KernelContext.Memory, 1UL << addrSpaceBits); CpuContext = new CpuContext(CpuMemory); // TODO: This should eventually be removed. // The GPU shouldn't depend on the CPU memory manager at all. - _system.Device.Gpu.SetVmm(CpuMemory); + KernelContext.Device.Gpu.SetVmm(CpuMemory); - MemoryManager = new KMemoryManager(_system, CpuMemory); + MemoryManager = new KMemoryManager(KernelContext, CpuMemory); } public void PrintCurrentThreadStackTrace() { - System.Scheduler.GetCurrentThread().PrintGuestStackTrace(); + KernelContext.Scheduler.GetCurrentThread().PrintGuestStackTrace(); } private void UndefinedInstructionHandler(object sender, InstUndefinedEventArgs e) diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs deleted file mode 100644 index d5698e2bc..000000000 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs +++ /dev/null @@ -1,44 +0,0 @@ -using ARMeilleure.State; -using Ryujinx.HLE.HOS.Kernel.Process; -using Ryujinx.HLE.HOS.Kernel.Threading; -using System; - -namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall -{ - partial class SvcHandler - { - private Switch _device; - private KProcess _process; - private Horizon _system; - - public SvcHandler(Switch device, KProcess process) - { - _device = device; - _process = process; - _system = device.System; - } - - public void SvcCall(object sender, InstExceptionEventArgs e) - { - ExecutionContext context = (ExecutionContext)sender; - - Action svcFunc = context.IsAarch32 ? SvcTable.SvcTable32[e.Id] : SvcTable.SvcTable64[e.Id]; - - if (svcFunc == null) - { - throw new NotImplementedException($"SVC 0x{e.Id:X4} is not implemented."); - } - - svcFunc(this, context); - - PostSvcHandler(); - } - - private void PostSvcHandler() - { - KThread currentThread = _system.Scheduler.GetCurrentThread(); - - currentThread.HandlePostSyscall(); - } - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcIpc.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcIpc.cs deleted file mode 100644 index 7188ead08..000000000 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcIpc.cs +++ /dev/null @@ -1,607 +0,0 @@ -using Ryujinx.Common.Logging; -using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel.Common; -using Ryujinx.HLE.HOS.Kernel.Ipc; -using Ryujinx.HLE.HOS.Kernel.Process; -using Ryujinx.HLE.HOS.Kernel.Threading; -using System.Threading; - -namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall -{ - partial class SvcHandler - { - private struct HleIpcMessage - { - public KThread Thread { get; private set; } - public KClientSession Session { get; private set; } - public IpcMessage Message { get; private set; } - public long MessagePtr { get; private set; } - - public HleIpcMessage( - KThread thread, - KClientSession session, - IpcMessage message, - long messagePtr) - { - Thread = thread; - Session = session; - Message = message; - MessagePtr = messagePtr; - } - } - - public KernelResult ConnectToNamedPort64([R(1)] ulong namePtr, [R(1)] out int handle) - { - return ConnectToNamedPort(namePtr, out handle); - } - - public KernelResult ConnectToNamedPort32([R(1)] uint namePtr, [R(1)] out int handle) - { - return ConnectToNamedPort(namePtr, out handle); - } - - private KernelResult ConnectToNamedPort(ulong namePtr, out int handle) - { - handle = 0; - - if (!KernelTransfer.UserToKernelString(_system, namePtr, 12, out string name)) - { - return KernelResult.UserCopyFailed; - } - - if (name.Length > 11) - { - return KernelResult.MaximumExceeded; - } - - KAutoObject autoObj = KAutoObject.FindNamedObject(_system, name); - - if (!(autoObj is KClientPort clientPort)) - { - return KernelResult.NotFound; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - KernelResult result = currentProcess.HandleTable.ReserveHandle(out handle); - - if (result != KernelResult.Success) - { - return result; - } - - result = clientPort.Connect(out KClientSession clientSession); - - if (result != KernelResult.Success) - { - currentProcess.HandleTable.CancelHandleReservation(handle); - - return result; - } - - currentProcess.HandleTable.SetReservedHandleObj(handle, clientSession); - - clientSession.DecrementReferenceCount(); - - return result; - } - - public KernelResult SendSyncRequest64([R(0)] int handle) - { - return SendSyncRequest((ulong)_system.Scheduler.GetCurrentThread().Context.Tpidr, 0x100, handle); - } - - public KernelResult SendSyncRequest32([R(0)] int handle) - { - return SendSyncRequest((ulong)_system.Scheduler.GetCurrentThread().Context.Tpidr, 0x100, handle); - } - - public KernelResult SendSyncRequestWithUserBuffer64([R(0)] ulong messagePtr, [R(1)] ulong size, [R(2)] int handle) - { - return SendSyncRequest(messagePtr, size, handle); - } - - public KernelResult SendSyncRequestWithUserBuffer32([R(0)] uint messagePtr, [R(1)] uint size, [R(2)] int handle) - { - return SendSyncRequest(messagePtr, size, handle); - } - - private KernelResult SendSyncRequest(ulong messagePtr, ulong size, int handle) - { - byte[] messageData = new byte[size]; - - _process.CpuMemory.Read(messagePtr, messageData); - - KClientSession clientSession = _process.HandleTable.GetObject(handle); - - if (clientSession == null || clientSession.Service == null) - { - return SendSyncRequest_(handle); - } - - if (clientSession != null) - { - _system.CriticalSection.Enter(); - - KThread currentThread = _system.Scheduler.GetCurrentThread(); - - currentThread.SignaledObj = null; - currentThread.ObjSyncResult = KernelResult.Success; - - currentThread.Reschedule(ThreadSchedState.Paused); - - IpcMessage message = new IpcMessage(messageData, (long)messagePtr); - - ThreadPool.QueueUserWorkItem(ProcessIpcRequest, new HleIpcMessage( - currentThread, - clientSession, - message, - (long)messagePtr)); - - _system.ThreadCounter.AddCount(); - - _system.CriticalSection.Leave(); - - return currentThread.ObjSyncResult; - } - else - { - Logger.PrintWarning(LogClass.KernelSvc, $"Invalid session handle 0x{handle:x8}!"); - - return KernelResult.InvalidHandle; - } - } - - private void ProcessIpcRequest(object state) - { - HleIpcMessage ipcMessage = (HleIpcMessage)state; - - ipcMessage.Thread.ObjSyncResult = IpcHandler.IpcCall( - _device, - _process, - _process.CpuMemory, - ipcMessage.Thread, - ipcMessage.Session, - ipcMessage.Message, - ipcMessage.MessagePtr); - - _system.ThreadCounter.Signal(); - - ipcMessage.Thread.Reschedule(ThreadSchedState.Running); - } - - private KernelResult SendSyncRequest_(int handle) - { - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - KClientSession session = currentProcess.HandleTable.GetObject(handle); - - if (session == null) - { - return KernelResult.InvalidHandle; - } - - return session.SendSyncRequest(); - } - - public KernelResult CreateSession64( - [R(2)] bool isLight, - [R(3)] ulong namePtr, - [R(1)] out int serverSessionHandle, - [R(2)] out int clientSessionHandle) - { - return CreateSession(isLight, namePtr, out serverSessionHandle, out clientSessionHandle); - } - - public KernelResult CreateSession32( - [R(2)] bool isLight, - [R(3)] uint namePtr, - [R(1)] out int serverSessionHandle, - [R(2)] out int clientSessionHandle) - { - return CreateSession(isLight, namePtr, out serverSessionHandle, out clientSessionHandle); - } - - private KernelResult CreateSession( - bool isLight, - ulong namePtr, - out int serverSessionHandle, - out int clientSessionHandle) - { - serverSessionHandle = 0; - clientSessionHandle = 0; - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - KResourceLimit resourceLimit = currentProcess.ResourceLimit; - - KernelResult result = KernelResult.Success; - - if (resourceLimit != null && !resourceLimit.Reserve(LimitableResource.Session, 1)) - { - return KernelResult.ResLimitExceeded; - } - - if (isLight) - { - KLightSession session = new KLightSession(_system); - - result = currentProcess.HandleTable.GenerateHandle(session.ServerSession, out serverSessionHandle); - - if (result == KernelResult.Success) - { - result = currentProcess.HandleTable.GenerateHandle(session.ClientSession, out clientSessionHandle); - - if (result != KernelResult.Success) - { - currentProcess.HandleTable.CloseHandle(serverSessionHandle); - - serverSessionHandle = 0; - } - } - - session.ServerSession.DecrementReferenceCount(); - session.ClientSession.DecrementReferenceCount(); - } - else - { - KSession session = new KSession(_system); - - result = currentProcess.HandleTable.GenerateHandle(session.ServerSession, out serverSessionHandle); - - if (result == KernelResult.Success) - { - result = currentProcess.HandleTable.GenerateHandle(session.ClientSession, out clientSessionHandle); - - if (result != KernelResult.Success) - { - currentProcess.HandleTable.CloseHandle(serverSessionHandle); - - serverSessionHandle = 0; - } - } - - session.ServerSession.DecrementReferenceCount(); - session.ClientSession.DecrementReferenceCount(); - } - - return result; - } - - public KernelResult AcceptSession64([R(1)] int portHandle, [R(1)] out int sessionHandle) - { - return AcceptSession(portHandle, out sessionHandle); - } - - public KernelResult AcceptSession32([R(1)] int portHandle, [R(1)] out int sessionHandle) - { - return AcceptSession(portHandle, out sessionHandle); - } - - private KernelResult AcceptSession(int portHandle, out int sessionHandle) - { - sessionHandle = 0; - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - KServerPort serverPort = currentProcess.HandleTable.GetObject(portHandle); - - if (serverPort == null) - { - return KernelResult.InvalidHandle; - } - - KernelResult result = currentProcess.HandleTable.ReserveHandle(out int handle); - - if (result != KernelResult.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 = KernelResult.Success; - } - else - { - currentProcess.HandleTable.CancelHandleReservation(handle); - - result = KernelResult.NotFound; - } - - return result; - } - - public KernelResult ReplyAndReceive64( - [R(1)] ulong handlesPtr, - [R(2)] int handlesCount, - [R(3)] int replyTargetHandle, - [R(4)] long timeout, - [R(1)] out int handleIndex) - { - return ReplyAndReceive(handlesPtr, handlesCount, replyTargetHandle, timeout, out handleIndex); - } - - public KernelResult ReplyAndReceive32( - [R(0)] uint timeoutLow, - [R(1)] ulong handlesPtr, - [R(2)] int handlesCount, - [R(3)] int replyTargetHandle, - [R(4)] uint timeoutHigh, - [R(1)] out int handleIndex) - { - long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32)); - - return ReplyAndReceive(handlesPtr, handlesCount, replyTargetHandle, timeout, out handleIndex); - } - - public KernelResult ReplyAndReceive( - ulong handlesPtr, - int handlesCount, - int replyTargetHandle, - long timeout, - out int handleIndex) - { - handleIndex = 0; - - if ((uint)handlesCount > 0x40) - { - return KernelResult.MaximumExceeded; - } - - KProcess currentProcess = _system.Scheduler.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.UserToKernelInt32Array(_system, handlesPtr, handles)) - { - return KernelResult.UserCopyFailed; - } - - KSynchronizationObject[] syncObjs = new KSynchronizationObject[handlesCount]; - - for (int index = 0; index < handlesCount; index++) - { - KSynchronizationObject obj = currentProcess.HandleTable.GetObject(handles[index]); - - if (obj == null) - { - return KernelResult.InvalidHandle; - } - - syncObjs[index] = obj; - } - - KernelResult result; - - if (replyTargetHandle != 0) - { - KServerSession replyTarget = currentProcess.HandleTable.GetObject(replyTargetHandle); - - if (replyTarget == null) - { - return KernelResult.InvalidHandle; - } - - result = replyTarget.Reply(); - - if (result != KernelResult.Success) - { - return result; - } - } - - while ((result = _system.Synchronization.WaitFor(syncObjs, timeout, out handleIndex)) == KernelResult.Success) - { - KServerSession session = currentProcess.HandleTable.GetObject(handles[handleIndex]); - - if (session == null) - { - break; - } - - if ((result = session.Receive()) != KernelResult.NotFound) - { - break; - } - } - - return result; - } - - public KernelResult CreatePort64( - [R(2)] int maxSessions, - [R(3)] bool isLight, - [R(4)] ulong namePtr, - [R(1)] out int serverPortHandle, - [R(2)] out int clientPortHandle) - { - return CreatePort(maxSessions, isLight, namePtr, out serverPortHandle, out clientPortHandle); - } - - public KernelResult CreatePort32( - [R(0)] uint namePtr, - [R(2)] int maxSessions, - [R(3)] bool isLight, - [R(1)] out int serverPortHandle, - [R(2)] out int clientPortHandle) - { - return CreatePort(maxSessions, isLight, namePtr, out serverPortHandle, out clientPortHandle); - } - - private KernelResult CreatePort( - int maxSessions, - bool isLight, - ulong namePtr, - out int serverPortHandle, - out int clientPortHandle) - { - serverPortHandle = clientPortHandle = 0; - - if (maxSessions < 1) - { - return KernelResult.MaximumExceeded; - } - - KPort port = new KPort(_system, maxSessions, isLight, (long)namePtr); - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - KernelResult result = currentProcess.HandleTable.GenerateHandle(port.ClientPort, out clientPortHandle); - - if (result != KernelResult.Success) - { - return result; - } - - result = currentProcess.HandleTable.GenerateHandle(port.ServerPort, out serverPortHandle); - - if (result != KernelResult.Success) - { - currentProcess.HandleTable.CloseHandle(clientPortHandle); - } - - return result; - } - - public KernelResult ManageNamedPort64([R(1)] ulong namePtr, [R(2)] int maxSessions, [R(1)] out int handle) - { - return ManageNamedPort(namePtr, maxSessions, out handle); - } - - public KernelResult ManageNamedPort32([R(1)] uint namePtr, [R(2)] int maxSessions, [R(1)] out int handle) - { - return ManageNamedPort(namePtr, maxSessions, out handle); - } - - private KernelResult ManageNamedPort(ulong namePtr, int maxSessions, out int handle) - { - handle = 0; - - if (!KernelTransfer.UserToKernelString(_system, namePtr, 12, out string name)) - { - return KernelResult.UserCopyFailed; - } - - if (maxSessions < 0 || name.Length > 11) - { - return KernelResult.MaximumExceeded; - } - - if (maxSessions == 0) - { - return KClientPort.RemoveName(_system, name); - } - - KPort port = new KPort(_system, maxSessions, false, 0); - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - KernelResult result = currentProcess.HandleTable.GenerateHandle(port.ServerPort, out handle); - - if (result != KernelResult.Success) - { - return result; - } - - result = port.ClientPort.SetName(name); - - if (result != KernelResult.Success) - { - currentProcess.HandleTable.CloseHandle(handle); - } - - return result; - } - - public KernelResult ConnectToPort64([R(1)] int clientPortHandle, [R(1)] out int clientSessionHandle) - { - return ConnectToPort(clientPortHandle, out clientSessionHandle); - } - - public KernelResult ConnectToPort32([R(1)] int clientPortHandle, [R(1)] out int clientSessionHandle) - { - return ConnectToPort(clientPortHandle, out clientSessionHandle); - } - - private KernelResult ConnectToPort(int clientPortHandle, out int clientSessionHandle) - { - clientSessionHandle = 0; - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - KClientPort clientPort = currentProcess.HandleTable.GetObject(clientPortHandle); - - if (clientPort == null) - { - return KernelResult.InvalidHandle; - } - - KernelResult result = currentProcess.HandleTable.ReserveHandle(out int handle); - - if (result != KernelResult.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 != KernelResult.Success) - { - currentProcess.HandleTable.CancelHandleReservation(handle); - - return result; - } - - currentProcess.HandleTable.SetReservedHandleObj(handle, session); - - session.DecrementReferenceCount(); - - clientSessionHandle = handle; - - return result; - } - } -} diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcMemory.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcMemory.cs deleted file mode 100644 index a6d069868..000000000 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcMemory.cs +++ /dev/null @@ -1,617 +0,0 @@ -using Ryujinx.HLE.HOS.Kernel.Common; -using Ryujinx.HLE.HOS.Kernel.Memory; -using Ryujinx.HLE.HOS.Kernel.Process; - -namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall -{ - partial class SvcHandler - { - public KernelResult SetHeapSize64([R(1)] ulong size, [R(1)] out ulong position) - { - return SetHeapSize(size, out position); - } - - public KernelResult SetHeapSize32([R(1)] uint size, [R(1)] out uint position) - { - ulong temporaryPosition; - - KernelResult result = SetHeapSize(size, out temporaryPosition); - - position = (uint)temporaryPosition; - - return result; - } - - private KernelResult SetHeapSize(ulong size, out ulong position) - { - if ((size & 0xfffffffe001fffff) != 0) - { - position = 0; - - return KernelResult.InvalidSize; - } - - return _process.MemoryManager.SetHeapSize(size, out position); - } - - public KernelResult SetMemoryAttribute64( - [R(0)] ulong position, - [R(1)] ulong size, - [R(2)] MemoryAttribute attributeMask, - [R(3)] MemoryAttribute attributeValue) - { - return SetMemoryAttribute(position, size, attributeMask, attributeValue); - } - - public KernelResult SetMemoryAttribute32( - [R(0)] uint position, - [R(1)] uint size, - [R(2)] MemoryAttribute attributeMask, - [R(3)] MemoryAttribute attributeValue) - { - return SetMemoryAttribute(position, size, attributeMask, attributeValue); - } - - private KernelResult SetMemoryAttribute( - ulong position, - ulong size, - MemoryAttribute attributeMask, - MemoryAttribute attributeValue) - { - if (!PageAligned(position)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - MemoryAttribute attributes = attributeMask | attributeValue; - - if (attributes != attributeMask || - (attributes | MemoryAttribute.Uncached) != MemoryAttribute.Uncached) - { - return KernelResult.InvalidCombination; - } - - KernelResult result = _process.MemoryManager.SetMemoryAttribute( - position, - size, - attributeMask, - attributeValue); - - return result; - } - - public KernelResult MapMemory64([R(0)] ulong dst, [R(1)] ulong src, [R(2)] ulong size) - { - return MapMemory(dst, src, size); - } - - public KernelResult MapMemory32([R(0)] uint dst, [R(1)] uint src, [R(2)] uint size) - { - return MapMemory(dst, src, size); - } - - private KernelResult MapMemory(ulong dst, ulong src, ulong size) - { - if (!PageAligned(src | dst)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - if (src + size <= src || dst + size <= dst) - { - return KernelResult.InvalidMemState; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - if (!currentProcess.MemoryManager.InsideAddrSpace(src, size)) - { - return KernelResult.InvalidMemState; - } - - if (currentProcess.MemoryManager.OutsideStackRegion(dst, size) || - currentProcess.MemoryManager.InsideHeapRegion (dst, size) || - currentProcess.MemoryManager.InsideAliasRegion (dst, size)) - { - return KernelResult.InvalidMemRange; - } - - return _process.MemoryManager.Map(dst, src, size); - } - - public KernelResult UnmapMemory64([R(0)] ulong dst, [R(1)] ulong src, [R(2)] ulong size) - { - return UnmapMemory(dst, src, size); - } - - public KernelResult UnmapMemory32([R(0)] uint dst, [R(1)] uint src, [R(2)] uint size) - { - return UnmapMemory(dst, src, size); - } - - private KernelResult UnmapMemory(ulong dst, ulong src, ulong size) - { - if (!PageAligned(src | dst)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - if (src + size <= src || dst + size <= dst) - { - return KernelResult.InvalidMemState; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - if (!currentProcess.MemoryManager.InsideAddrSpace(src, size)) - { - return KernelResult.InvalidMemState; - } - - if (currentProcess.MemoryManager.OutsideStackRegion(dst, size) || - currentProcess.MemoryManager.InsideHeapRegion (dst, size) || - currentProcess.MemoryManager.InsideAliasRegion (dst, size)) - { - return KernelResult.InvalidMemRange; - } - - return _process.MemoryManager.Unmap(dst, src, size); - } - - public KernelResult QueryMemory64([R(0)] ulong infoPtr, [R(2)] ulong position, [R(1)] out ulong pageInfo) - { - return QueryMemory(infoPtr, position, out pageInfo); - } - - public KernelResult QueryMemory32([R(0)] uint infoPtr, [R(1)] uint r1, [R(2)] uint position, [R(1)] out uint pageInfo) - { - KernelResult result = QueryMemory(infoPtr, position, out ulong pageInfo64); - - pageInfo = (uint)pageInfo64; - - return result; - } - - private KernelResult QueryMemory(ulong infoPtr, ulong position, out ulong pageInfo) - { - KMemoryInfo blkInfo = _process.MemoryManager.QueryMemory(position); - - _process.CpuMemory.Write(infoPtr + 0x00, blkInfo.Address); - _process.CpuMemory.Write(infoPtr + 0x08, blkInfo.Size); - _process.CpuMemory.Write(infoPtr + 0x10, (int)blkInfo.State & 0xff); - _process.CpuMemory.Write(infoPtr + 0x14, (int)blkInfo.Attribute); - _process.CpuMemory.Write(infoPtr + 0x18, (int)blkInfo.Permission); - _process.CpuMemory.Write(infoPtr + 0x1c, blkInfo.IpcRefCount); - _process.CpuMemory.Write(infoPtr + 0x20, blkInfo.DeviceRefCount); - _process.CpuMemory.Write(infoPtr + 0x24, 0); - - pageInfo = 0; - - return KernelResult.Success; - } - - public KernelResult MapSharedMemory64([R(0)] int handle, [R(1)] ulong address, [R(2)] ulong size, [R(3)] MemoryPermission permission) - { - return MapSharedMemory(handle, address, size, permission); - } - - public KernelResult MapSharedMemory32([R(0)] int handle, [R(1)] uint address, [R(2)] uint size, [R(3)] MemoryPermission permission) - { - return MapSharedMemory(handle, address, size, permission); - } - - private KernelResult MapSharedMemory(int handle, ulong address, ulong size, MemoryPermission permission) - { - if (!PageAligned(address)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - if (address + size <= address) - { - return KernelResult.InvalidMemState; - } - - if ((permission | MemoryPermission.Write) != MemoryPermission.ReadAndWrite) - { - return KernelResult.InvalidPermission; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - KSharedMemory sharedMemory = currentProcess.HandleTable.GetObject(handle); - - if (sharedMemory == null) - { - return KernelResult.InvalidHandle; - } - - if (currentProcess.MemoryManager.IsInvalidRegion (address, size) || - currentProcess.MemoryManager.InsideHeapRegion (address, size) || - currentProcess.MemoryManager.InsideAliasRegion(address, size)) - { - return KernelResult.InvalidMemRange; - } - - return sharedMemory.MapIntoProcess( - currentProcess.MemoryManager, - address, - size, - currentProcess, - permission); - } - - public KernelResult UnmapSharedMemory64([R(0)] int handle, [R(1)] ulong address, [R(2)] ulong size) - { - return UnmapSharedMemory(handle, address, size); - } - - public KernelResult UnmapSharedMemory32([R(0)] int handle, [R(1)] uint address, [R(2)] uint size) - { - return UnmapSharedMemory(handle, address, size); - } - - private KernelResult UnmapSharedMemory(int handle, ulong address, ulong size) - { - if (!PageAligned(address)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - if (address + size <= address) - { - return KernelResult.InvalidMemState; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - KSharedMemory sharedMemory = currentProcess.HandleTable.GetObject(handle); - - if (sharedMemory == null) - { - return KernelResult.InvalidHandle; - } - - if (currentProcess.MemoryManager.IsInvalidRegion (address, size) || - currentProcess.MemoryManager.InsideHeapRegion (address, size) || - currentProcess.MemoryManager.InsideAliasRegion(address, size)) - { - return KernelResult.InvalidMemRange; - } - - return sharedMemory.UnmapFromProcess( - currentProcess.MemoryManager, - address, - size, - currentProcess); - } - - public KernelResult CreateTransferMemory64( - [R(1)] ulong address, - [R(2)] ulong size, - [R(3)] MemoryPermission permission, - [R(1)] out int handle) - { - return CreateTransferMemory(address, size, permission, out handle); - } - - public KernelResult CreateTransferMemory32( - [R(1)] uint address, - [R(2)] uint size, - [R(3)] MemoryPermission permission, - [R(1)] out int handle) - { - return CreateTransferMemory(address, size, permission, out handle); - } - - private KernelResult CreateTransferMemory(ulong address, ulong size, MemoryPermission permission, out int handle) - { - handle = 0; - - if (!PageAligned(address)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - if (address + size <= address) - { - return KernelResult.InvalidMemState; - } - - if (permission > MemoryPermission.ReadAndWrite || permission == MemoryPermission.Write) - { - return KernelResult.InvalidPermission; - } - - KernelResult result = _process.MemoryManager.ReserveTransferMemory(address, size, permission); - - if (result != KernelResult.Success) - { - return result; - } - - KTransferMemory transferMemory = new KTransferMemory(_system, address, size); - - return _process.HandleTable.GenerateHandle(transferMemory, out handle); - } - - public KernelResult MapPhysicalMemory64([R(0)] ulong address, [R(1)] ulong size) - { - return MapPhysicalMemory(address, size); - } - - public KernelResult MapPhysicalMemory32([R(0)] uint address, [R(1)] uint size) - { - return MapPhysicalMemory(address, size); - } - - private KernelResult MapPhysicalMemory(ulong address, ulong size) - { - if (!PageAligned(address)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - if (address + size <= address) - { - return KernelResult.InvalidMemRange; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - if ((currentProcess.PersonalMmHeapPagesCount & 0xfffffffffffff) == 0) - { - return KernelResult.InvalidState; - } - - if (!currentProcess.MemoryManager.InsideAddrSpace (address, size) || - currentProcess.MemoryManager.OutsideAliasRegion(address, size)) - { - return KernelResult.InvalidMemRange; - } - - return _process.MemoryManager.MapPhysicalMemory(address, size); - } - - public KernelResult UnmapPhysicalMemory64([R(0)] ulong address, [R(1)] ulong size) - { - return UnmapPhysicalMemory(address, size); - } - - public KernelResult UnmapPhysicalMemory32([R(0)] uint address, [R(1)] uint size) - { - return UnmapPhysicalMemory(address, size); - } - - private KernelResult UnmapPhysicalMemory(ulong address, ulong size) - { - if (!PageAligned(address)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - if (address + size <= address) - { - return KernelResult.InvalidMemRange; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - if ((currentProcess.PersonalMmHeapPagesCount & 0xfffffffffffff) == 0) - { - return KernelResult.InvalidState; - } - - if (!currentProcess.MemoryManager.InsideAddrSpace (address, size) || - currentProcess.MemoryManager.OutsideAliasRegion(address, size)) - { - return KernelResult.InvalidMemRange; - } - - return _process.MemoryManager.UnmapPhysicalMemory(address, size); - } - - public KernelResult MapProcessCodeMemory64([R(0)] int handle, [R(1)] ulong dst, [R(2)] ulong src, [R(3)] ulong size) - { - return MapProcessCodeMemory(handle, dst, src, size); - } - - public KernelResult MapProcessCodeMemory32([R(0)] int handle, [R(1)] uint srcLow, [R(2)] uint dstLow, [R(3)] uint dstHigh, [R(4)] uint srcHigh, [R(5)] uint sizeLow, [R(6)] uint sizeHigh) - { - ulong src = (srcLow | ((ulong)srcHigh << 32)); - ulong dst = (dstLow | ((ulong)dstHigh << 32)); - ulong size = (sizeLow | ((ulong)sizeHigh << 32)); - - return MapProcessCodeMemory(handle, dst, src, size); - } - - public KernelResult 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 = _system.Scheduler.GetCurrentProcess(); - - KProcess targetProcess = currentProcess.HandleTable.GetObject(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); - } - - public KernelResult UnmapProcessCodeMemory64([R(0)] int handle, [R(1)] ulong dst, [R(2)] ulong src, [R(3)] ulong size) - { - return UnmapProcessCodeMemory(handle, dst, src, size); - } - - public KernelResult UnmapProcessCodeMemory32([R(0)] int handle, [R(1)] uint srcLow, [R(2)] uint dstLow, [R(3)] uint dstHigh, [R(4)] uint srcHigh, [R(5)] uint sizeLow, [R(6)] uint sizeHigh) - { - ulong src = (srcLow | ((ulong)srcHigh << 32)); - ulong dst = (dstLow | ((ulong)dstHigh << 32)); - ulong size = (sizeLow | ((ulong)sizeHigh << 32)); - - return UnmapProcessCodeMemory(handle, dst, src, size); - } - - public KernelResult 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 = _system.Scheduler.GetCurrentProcess(); - - KProcess targetProcess = currentProcess.HandleTable.GetObject(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); - } - - public KernelResult SetProcessMemoryPermission64([R(0)] int handle, [R(1)] ulong src, [R(2)] ulong size, [R(3)] MemoryPermission permission) - { - return SetProcessMemoryPermission(handle, src, size, permission); - } - - public KernelResult SetProcessMemoryPermission32( - [R(0)] int handle, - [R(1)] uint sizeLow, - [R(2)] uint srcLow, - [R(3)] uint srcHigh, - [R(4)] uint sizeHigh, - [R(5)] MemoryPermission permission) - { - ulong src = (srcLow | ((ulong)srcHigh << 32)); - ulong size = (sizeLow | ((ulong)sizeHigh << 32)); - - return SetProcessMemoryPermission(handle, src, size, permission); - } - - public KernelResult SetProcessMemoryPermission(int handle, ulong src, ulong size, MemoryPermission permission) - { - if (!PageAligned(src)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - if (permission != MemoryPermission.None && - permission != MemoryPermission.Read && - permission != MemoryPermission.ReadAndWrite && - permission != MemoryPermission.ReadAndExecute) - { - return KernelResult.InvalidPermission; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - KProcess targetProcess = currentProcess.HandleTable.GetObject(handle); - - if (targetProcess == null) - { - return KernelResult.InvalidHandle; - } - - if (targetProcess.MemoryManager.OutsideAddrSpace(src, size)) - { - return KernelResult.InvalidMemState; - } - - return targetProcess.MemoryManager.SetProcessMemoryPermission(src, size, permission); - } - - private static bool PageAligned(ulong position) - { - return (position & (KMemoryManager.PageSize - 1)) == 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs deleted file mode 100644 index f654630ce..000000000 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs +++ /dev/null @@ -1,732 +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; - -namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall -{ - partial class SvcHandler - { - public void ExitProcess64() - { - ExitProcess(); - } - - public void ExitProcess32() - { - ExitProcess(); - } - - public KernelResult TerminateProcess64([R(0)] int handle) - { - return TerminateProcess(handle); - } - - public KernelResult TerminateProcess32([R(0)] int handle) - { - return TerminateProcess(handle); - } - - private KernelResult TerminateProcess(int handle) - { - KProcess process = _process.HandleTable.GetObject(handle); - - KernelResult result; - - if (process != null) - { - if (process == _system.Scheduler.GetCurrentProcess()) - { - result = KernelResult.Success; - process.DecrementToZeroWhileTerminatingCurrent(); - } - else - { - result = process.Terminate(); - process.DecrementReferenceCount(); - } - } - else - { - result = KernelResult.InvalidHandle; - } - - return result; - } - - private void ExitProcess() - { - _system.Scheduler.GetCurrentProcess().TerminateCurrentProcess(); - } - - public KernelResult SignalEvent64([R(0)] int handle) - { - return SignalEvent(handle); - } - - public KernelResult SignalEvent32([R(0)] int handle) - { - return SignalEvent(handle); - } - - private KernelResult SignalEvent(int handle) - { - KWritableEvent writableEvent = _process.HandleTable.GetObject(handle); - - KernelResult result; - - if (writableEvent != null) - { - writableEvent.Signal(); - - result = KernelResult.Success; - } - else - { - result = KernelResult.InvalidHandle; - } - - return result; - } - - public KernelResult ClearEvent64([R(0)] int handle) - { - return ClearEvent(handle); - } - - public KernelResult ClearEvent32([R(0)] int handle) - { - return ClearEvent(handle); - } - - private KernelResult ClearEvent(int handle) - { - KernelResult result; - - KWritableEvent writableEvent = _process.HandleTable.GetObject(handle); - - if (writableEvent == null) - { - KReadableEvent readableEvent = _process.HandleTable.GetObject(handle); - - result = readableEvent?.Clear() ?? KernelResult.InvalidHandle; - } - else - { - result = writableEvent.Clear(); - } - - return result; - } - - public KernelResult CloseHandle64([R(0)] int handle) - { - return CloseHandle(handle); - } - - public KernelResult CloseHandle32([R(0)] int handle) - { - return CloseHandle(handle); - } - - private KernelResult CloseHandle(int handle) - { - KAutoObject obj = _process.HandleTable.GetObject(handle); - - _process.HandleTable.CloseHandle(handle); - - if (obj == null) - { - return KernelResult.InvalidHandle; - } - - if (obj is KSession session) - { - session.Dispose(); - } - else if (obj is KTransferMemory transferMemory) - { - _process.MemoryManager.ResetTransferMemory( - transferMemory.Address, - transferMemory.Size); - } - - return KernelResult.Success; - } - - public KernelResult ResetSignal64([R(0)] int handle) - { - return ResetSignal(handle); - } - - public KernelResult ResetSignal32([R(0)] int handle) - { - return ResetSignal(handle); - } - - private KernelResult ResetSignal(int handle) - { - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - KReadableEvent readableEvent = currentProcess.HandleTable.GetObject(handle); - - KernelResult 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; - } - - public ulong GetSystemTick64() - { - return _system.Scheduler.GetCurrentThread().Context.CntpctEl0; - } - - public void GetSystemTick32([R(0)] out uint resultLow, [R(1)] out uint resultHigh) - { - ulong result = _system.Scheduler.GetCurrentThread().Context.CntpctEl0; - - resultLow = (uint)(result & uint.MaxValue); - resultHigh = (uint)(result >> 32); - } - - public KernelResult GetProcessId64([R(1)] int handle, [R(1)] out long pid) - { - return GetProcessId(handle, out pid); - } - - public KernelResult GetProcessId32([R(1)] int handle, [R(1)] out int pidLow, [R(2)] out int pidHigh) - { - KernelResult result = GetProcessId(handle, out long pid); - - pidLow = (int)(pid & uint.MaxValue); - pidHigh = (int)(pid >> 32); - - return result; - } - - private KernelResult GetProcessId(int handle, out long pid) - { - KProcess currentProcess = _system.Scheduler.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 - ? KernelResult.Success - : KernelResult.InvalidHandle; - } - - public void Break64([R(0)] ulong reason, [R(1)] ulong x1, [R(2)] ulong info) - { - Break(reason); - } - - public void Break32([R(0)] uint reason, [R(1)] uint r1, [R(2)] uint info) - { - Break(reason); - } - - private void Break(ulong reason) - { - KThread currentThread = _system.Scheduler.GetCurrentThread(); - - if ((reason & (1UL << 31)) == 0) - { - currentThread.PrintGuestStackTrace(); - - // 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.PrintInfo(LogClass.KernelSvc, "Debugger triggered."); - - currentThread.PrintGuestStackTrace(); - } - } - - public void OutputDebugString64([R(0)] ulong strPtr, [R(1)] ulong size) - { - OutputDebugString(strPtr, size); - } - - public void OutputDebugString32([R(0)] uint strPtr, [R(1)] uint size) - { - OutputDebugString(strPtr, size); - } - - private void OutputDebugString(ulong strPtr, ulong size) - { - string str = MemoryHelper.ReadAsciiString(_process.CpuMemory, (long)strPtr, (long)size); - - Logger.PrintWarning(LogClass.KernelSvc, str); - } - - public KernelResult GetInfo64([R(1)] uint id, [R(2)] int handle, [R(3)] long subId, [R(1)] out long value) - { - return GetInfo(id, handle, subId, out value); - } - - public KernelResult GetInfo32( - [R(0)] uint subIdLow, - [R(1)] uint id, - [R(2)] int handle, - [R(3)] uint subIdHigh, - [R(1)] out uint valueLow, - [R(2)] out uint valueHigh) - { - long subId = (long)(subIdLow | ((ulong)subIdHigh << 32)); - - KernelResult result = GetInfo(id, handle, subId, out long value); - valueHigh = (uint)(value >> 32); - valueLow = (uint)(value & uint.MaxValue); - - return result; - } - - private KernelResult GetInfo(uint id, int handle, long subId, out long value) - { - value = 0; - - switch (id) - { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 12: - case 13: - case 14: - case 15: - case 16: - case 17: - case 18: - case 20: - case 21: - case 22: - { - if (subId != 0) - { - return KernelResult.InvalidCombination; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - KProcess process = currentProcess.HandleTable.GetKProcess(handle); - - if (process == null) - { - return KernelResult.InvalidHandle; - } - - switch (id) - { - case 0: value = process.Capabilities.AllowedCpuCoresMask; break; - case 1: value = process.Capabilities.AllowedThreadPriosMask; break; - - case 2: value = (long)process.MemoryManager.AliasRegionStart; break; - case 3: value = (long)(process.MemoryManager.AliasRegionEnd - - process.MemoryManager.AliasRegionStart); break; - - case 4: value = (long)process.MemoryManager.HeapRegionStart; break; - case 5: value = (long)(process.MemoryManager.HeapRegionEnd - - process.MemoryManager.HeapRegionStart); break; - - case 6: value = (long)process.GetMemoryCapacity(); break; - - case 7: value = (long)process.GetMemoryUsage(); break; - - case 12: value = (long)process.MemoryManager.GetAddrSpaceBaseAddr(); break; - - case 13: value = (long)process.MemoryManager.GetAddrSpaceSize(); break; - - case 14: value = (long)process.MemoryManager.StackRegionStart; break; - case 15: value = (long)(process.MemoryManager.StackRegionEnd - - process.MemoryManager.StackRegionStart); break; - - case 16: value = (long)process.PersonalMmHeapPagesCount * KMemoryManager.PageSize; break; - - case 17: - if (process.PersonalMmHeapPagesCount != 0) - { - value = process.MemoryManager.GetMmUsedPages() * KMemoryManager.PageSize; - } - - break; - - case 18: value = (long)process.TitleId; break; - - case 20: value = (long)process.UserExceptionContextAddress; break; - - case 21: value = (long)process.GetMemoryCapacityWithoutPersonalMmHeap(); break; - - case 22: value = (long)process.GetMemoryUsageWithoutPersonalMmHeap(); break; - } - - break; - } - - case 8: - { - if (handle != 0) - { - return KernelResult.InvalidHandle; - } - - if (subId != 0) - { - return KernelResult.InvalidCombination; - } - - value = _system.Scheduler.GetCurrentProcess().Debug ? 1 : 0; - - break; - } - - case 9: - { - if (handle != 0) - { - return KernelResult.InvalidHandle; - } - - if (subId != 0) - { - return KernelResult.InvalidCombination; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - if (currentProcess.ResourceLimit != null) - { - KHandleTable handleTable = currentProcess.HandleTable; - KResourceLimit resourceLimit = currentProcess.ResourceLimit; - - KernelResult result = handleTable.GenerateHandle(resourceLimit, out int resLimHandle); - - if (result != KernelResult.Success) - { - return result; - } - - value = (uint)resLimHandle; - } - - break; - } - - case 10: - { - if (handle != 0) - { - return KernelResult.InvalidHandle; - } - - int currentCore = _system.Scheduler.GetCurrentThread().CurrentCore; - - if (subId != -1 && subId != currentCore) - { - return KernelResult.InvalidCombination; - } - - value = _system.Scheduler.CoreContexts[currentCore].TotalIdleTimeTicks; - - break; - } - - case 11: - { - if (handle != 0) - { - return KernelResult.InvalidHandle; - } - - if ((ulong)subId > 3) - { - return KernelResult.InvalidCombination; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - - value = currentProcess.RandomEntropy[subId]; - - break; - } - - case 0xf0000002u: - { - if (subId < -1 || subId > 3) - { - return KernelResult.InvalidCombination; - } - - KThread thread = _system.Scheduler.GetCurrentProcess().HandleTable.GetKThread(handle); - - if (thread == null) - { - return KernelResult.InvalidHandle; - } - - KThread currentThread = _system.Scheduler.GetCurrentThread(); - - int currentCore = currentThread.CurrentCore; - - if (subId != -1 && subId != currentCore) - { - return KernelResult.Success; - } - - KCoreContext coreContext = _system.Scheduler.CoreContexts[currentCore]; - - long timeDelta = PerformanceCounter.ElapsedMilliseconds - coreContext.LastContextSwitchTime; - - if (subId != -1) - { - value = KTimeManager.ConvertMillisecondsToTicks(timeDelta); - } - else - { - long totalTimeRunning = thread.TotalTimeRunning; - - if (thread == currentThread) - { - totalTimeRunning += timeDelta; - } - - value = KTimeManager.ConvertMillisecondsToTicks(totalTimeRunning); - } - - break; - } - - default: return KernelResult.InvalidEnumValue; - } - - return KernelResult.Success; - } - - public KernelResult CreateEvent64([R(1)] out int wEventHandle, [R(2)] out int rEventHandle) - { - return CreateEvent(out wEventHandle, out rEventHandle); - } - - public KernelResult CreateEvent32([R(1)] out int wEventHandle, [R(2)] out int rEventHandle) - { - return CreateEvent(out wEventHandle, out rEventHandle); - } - - private KernelResult CreateEvent(out int wEventHandle, out int rEventHandle) - { - KEvent Event = new KEvent(_system); - - KernelResult result = _process.HandleTable.GenerateHandle(Event.WritableEvent, out wEventHandle); - - if (result == KernelResult.Success) - { - result = _process.HandleTable.GenerateHandle(Event.ReadableEvent, out rEventHandle); - - if (result != KernelResult.Success) - { - _process.HandleTable.CloseHandle(wEventHandle); - } - } - else - { - rEventHandle = 0; - } - - return result; - } - - public KernelResult GetProcessList64([R(1)] ulong address, [R(2)] int maxCount, [R(1)] out int count) - { - return GetProcessList(address, maxCount, out count); - } - - public KernelResult GetProcessList32([R(1)] ulong address, [R(2)] int maxCount, [R(1)] out int count) - { - return GetProcessList(address, maxCount, out count); - } - - private KernelResult GetProcessList(ulong address, int maxCount, out int count) - { - count = 0; - - if ((maxCount >> 28) != 0) - { - return KernelResult.MaximumExceeded; - } - - if (maxCount != 0) - { - KProcess currentProcess = _system.Scheduler.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 (_system.Processes) - { - foreach (KProcess process in _system.Processes.Values) - { - if (copyCount < maxCount) - { - if (!KernelTransfer.KernelToUserInt64(_system, address + (ulong)copyCount * 8, process.Pid)) - { - return KernelResult.UserCopyFailed; - } - } - - copyCount++; - } - } - - count = copyCount; - - return KernelResult.Success; - } - - public KernelResult GetSystemInfo64([R(1)] uint id, [R(2)] int handle, [R(3)] long subId, [R(1)] out long value) - { - return GetSystemInfo(id, handle, subId, out value); - } - - public KernelResult GetSystemInfo32([R(1)] uint subIdLow, [R(2)] uint id, [R(3)] int handle, [R(3)] uint subIdHigh, [R(1)] out int valueLow, [R(2)] out int valueHigh) - { - long subId = (long)(subIdLow | ((ulong)subIdHigh << 32)); - - KernelResult result = GetSystemInfo(id, handle, subId, out long value); - - valueHigh = (int)(value >> 32); - valueLow = (int)(value & uint.MaxValue); - - return result; - } - - private KernelResult GetSystemInfo(uint id, int handle, long subId, out long value) - { - 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 = _system.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 * KMemoryManager.PageSize); - - break; - } - } - } - else /* if (Id == 2) */ - { - if ((ulong)subId > 1) - { - return KernelResult.InvalidCombination; - } - - switch (subId) - { - case 0: value = _system.PrivilegedProcessLowestId; break; - case 1: value = _system.PrivilegedProcessHighestId; break; - } - } - - return KernelResult.Success; - } - - public KernelResult FlushProcessDataCache32( - [R(0)] uint processHandle, - [R(2)] uint addressLow, - [R(3)] uint addressHigh, - [R(1)] uint sizeLow, - [R(4)] uint sizeHigh) - { - // 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 KernelResult.Success; - } - } -} diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs deleted file mode 100644 index f1ac3deda..000000000 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs +++ /dev/null @@ -1,520 +0,0 @@ -using ARMeilleure.State; -using Ryujinx.Cpu; -using Ryujinx.HLE.HOS.Kernel.Common; -using Ryujinx.HLE.HOS.Kernel.Process; -using Ryujinx.HLE.HOS.Kernel.Threading; - -namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall -{ - partial class SvcHandler - { - public KernelResult CreateThread64( - [R(1)] ulong entrypoint, - [R(2)] ulong argsPtr, - [R(3)] ulong stackTop, - [R(4)] int priority, - [R(5)] int cpuCore, - [R(1)] out int handle) - { - return CreateThread(entrypoint, argsPtr, stackTop, priority, cpuCore, out handle); - } - - public KernelResult CreateThread32( - [R(1)] uint entrypoint, - [R(2)] uint argsPtr, - [R(3)] uint stackTop, - [R(0)] int priority, - [R(4)] int cpuCore, - [R(1)] out int handle) - { - return CreateThread(entrypoint, argsPtr, stackTop, priority, cpuCore, out handle); - } - - private KernelResult CreateThread( - ulong entrypoint, - ulong argsPtr, - ulong stackTop, - int priority, - int cpuCore, - out int handle) - { - handle = 0; - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - if (cpuCore == -2) - { - cpuCore = currentProcess.DefaultCpuCore; - } - - if ((uint)cpuCore >= KScheduler.CpuCoresCount || !currentProcess.IsCpuCoreAllowed(cpuCore)) - { - return KernelResult.InvalidCpuCore; - } - - if ((uint)priority >= KScheduler.PrioritiesCount || !currentProcess.IsPriorityAllowed(priority)) - { - return KernelResult.InvalidPriority; - } - - long timeout = KTimeManager.ConvertMillisecondsToNanoseconds(100); - - if (currentProcess.ResourceLimit != null && - !currentProcess.ResourceLimit.Reserve(LimitableResource.Thread, 1, timeout)) - { - return KernelResult.ResLimitExceeded; - } - - KThread thread = new KThread(_system); - - KernelResult result = currentProcess.InitializeThread( - thread, - entrypoint, - argsPtr, - stackTop, - priority, - cpuCore); - - if (result == KernelResult.Success) - { - result = _process.HandleTable.GenerateHandle(thread, out handle); - } - else - { - currentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1); - } - - thread.DecrementReferenceCount(); - - return result; - } - - public KernelResult StartThread64([R(0)] int handle) - { - return StartThread(handle); - } - - public KernelResult StartThread32([R(0)] int handle) - { - return StartThread(handle); - } - - private KernelResult StartThread(int handle) - { - KThread thread = _process.HandleTable.GetKThread(handle); - - if (thread != null) - { - thread.IncrementReferenceCount(); - - KernelResult result = thread.Start(); - - if (result == KernelResult.Success) - { - thread.IncrementReferenceCount(); - } - - thread.DecrementReferenceCount(); - - return result; - } - else - { - return KernelResult.InvalidHandle; - } - } - - public void ExitThread64() - { - ExitThread(); - } - - public void ExitThread32() - { - ExitThread(); - } - - private void ExitThread() - { - KThread currentThread = _system.Scheduler.GetCurrentThread(); - - _system.Scheduler.ExitThread(currentThread); - - currentThread.Exit(); - } - - public void SleepThread64([R(0)] long timeout) - { - SleepThread(timeout); - } - - public void SleepThread32([R(0)] uint timeoutLow, [R(1)] uint timeoutHigh) - { - long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32)); - - SleepThread(timeout); - } - - private void SleepThread(long timeout) - { - KThread currentThread = _system.Scheduler.GetCurrentThread(); - - if (timeout < 1) - { - switch (timeout) - { - case 0: currentThread.Yield(); break; - case -1: currentThread.YieldWithLoadBalancing(); break; - case -2: currentThread.YieldAndWaitForLoadBalancing(); break; - } - } - else - { - currentThread.Sleep(timeout); - } - } - - public KernelResult GetThreadPriority64([R(1)] int handle, [R(1)] out int priority) - { - return GetThreadPriority(handle, out priority); - } - - public KernelResult GetThreadPriority32([R(1)] int handle, [R(1)] out int priority) - { - return GetThreadPriority(handle, out priority); - } - - private KernelResult GetThreadPriority(int handle, out int priority) - { - KThread thread = _process.HandleTable.GetKThread(handle); - - if (thread != null) - { - priority = thread.DynamicPriority; - - return KernelResult.Success; - } - else - { - priority = 0; - - return KernelResult.InvalidHandle; - } - } - - public KernelResult SetThreadPriority64([R(0)] int handle, [R(1)] int priority) - { - return SetThreadPriority(handle, priority); - } - - public KernelResult SetThreadPriority32([R(0)] int handle, [R(1)] int priority) - { - return SetThreadPriority(handle, priority); - } - - public KernelResult SetThreadPriority(int handle, int priority) - { - // TODO: NPDM check. - - KThread thread = _process.HandleTable.GetKThread(handle); - - if (thread == null) - { - return KernelResult.InvalidHandle; - } - - thread.SetPriority(priority); - - return KernelResult.Success; - } - - public KernelResult GetThreadCoreMask64([R(2)] int handle, [R(1)] out int preferredCore, [R(2)] out long affinityMask) - { - return GetThreadCoreMask(handle, out preferredCore, out affinityMask); - } - - public KernelResult GetThreadCoreMask32([R(2)] int handle, [R(1)] out int preferredCore, [R(2)] out int affinityMaskLow, [R(3)] out int affinityMaskHigh) - { - KernelResult result = GetThreadCoreMask(handle, out preferredCore, out long affinityMask); - - affinityMaskLow = (int)(affinityMask >> 32); - affinityMaskHigh = (int)(affinityMask & uint.MaxValue); - - return result; - } - - private KernelResult GetThreadCoreMask(int handle, out int preferredCore, out long affinityMask) - { - KThread thread = _process.HandleTable.GetKThread(handle); - - if (thread != null) - { - preferredCore = thread.PreferredCore; - affinityMask = thread.AffinityMask; - - return KernelResult.Success; - } - else - { - preferredCore = 0; - affinityMask = 0; - - return KernelResult.InvalidHandle; - } - } - - public KernelResult SetThreadCoreMask64([R(0)] int handle, [R(1)] int preferredCore, [R(2)] long affinityMask) - { - return SetThreadCoreMask(handle, preferredCore, affinityMask); - } - - public KernelResult SetThreadCoreMask32([R(0)] int handle, [R(1)] int preferredCore, [R(2)] uint affinityMaskLow, [R(3)] uint affinityMaskHigh) - { - long affinityMask = (long)(affinityMaskLow | ((ulong)affinityMaskHigh << 32)); - - return SetThreadCoreMask(handle, preferredCore, affinityMask); - } - - private KernelResult SetThreadCoreMask(int handle, int preferredCore, long affinityMask) - { - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - if (preferredCore == -2) - { - preferredCore = currentProcess.DefaultCpuCore; - - affinityMask = 1 << preferredCore; - } - else - { - if ((currentProcess.Capabilities.AllowedCpuCoresMask | affinityMask) != - currentProcess.Capabilities.AllowedCpuCoresMask) - { - return KernelResult.InvalidCpuCore; - } - - if (affinityMask == 0) - { - return KernelResult.InvalidCombination; - } - - if ((uint)preferredCore > 3) - { - if ((preferredCore | 2) != -1) - { - return KernelResult.InvalidCpuCore; - } - } - else if ((affinityMask & (1 << preferredCore)) == 0) - { - return KernelResult.InvalidCombination; - } - } - - KThread thread = _process.HandleTable.GetKThread(handle); - - if (thread == null) - { - return KernelResult.InvalidHandle; - } - - return thread.SetCoreAndAffinityMask(preferredCore, affinityMask); - } - - public int GetCurrentProcessorNumber64() - { - return _system.Scheduler.GetCurrentThread().CurrentCore; - } - - public int GetCurrentProcessorNumber32() - { - return _system.Scheduler.GetCurrentThread().CurrentCore; - } - - public KernelResult GetThreadId64([R(1)] int handle, [R(1)] out long threadUid) - { - return GetThreadId(handle, out threadUid); - } - - public KernelResult GetThreadId32([R(1)] int handle, [R(1)] out uint threadUidLow, [R(2)] out uint threadUidHigh) - { - long threadUid; - - KernelResult result = GetThreadId(handle, out threadUid); - - threadUidLow = (uint)(threadUid >> 32); - threadUidHigh = (uint)(threadUid & uint.MaxValue); - - return result; - } - - private KernelResult GetThreadId(int handle, out long threadUid) - { - KThread thread = _process.HandleTable.GetKThread(handle); - - if (thread != null) - { - threadUid = thread.ThreadUid; - - return KernelResult.Success; - } - else - { - threadUid = 0; - - return KernelResult.InvalidHandle; - } - } - - public KernelResult SetThreadActivity64([R(0)] int handle, [R(1)] bool pause) - { - return SetThreadActivity(handle, pause); - } - - public KernelResult SetThreadActivity32([R(0)] int handle, [R(1)] bool pause) - { - return SetThreadActivity(handle, pause); - } - - private KernelResult SetThreadActivity(int handle, bool pause) - { - KThread thread = _process.HandleTable.GetObject(handle); - - if (thread == null) - { - return KernelResult.InvalidHandle; - } - - if (thread.Owner != _system.Scheduler.GetCurrentProcess()) - { - return KernelResult.InvalidHandle; - } - - if (thread == _system.Scheduler.GetCurrentThread()) - { - return KernelResult.InvalidThread; - } - - return thread.SetActivity(pause); - } - - public KernelResult GetThreadContext364([R(0)] ulong address, [R(1)] int handle) - { - return GetThreadContext3(address, handle); - } - - public KernelResult GetThreadContext332([R(0)] uint address, [R(1)] int handle) - { - return GetThreadContext3(address, handle); - } - - private KernelResult GetThreadContext3(ulong address, int handle) - { - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - KThread currentThread = _system.Scheduler.GetCurrentThread(); - - KThread thread = _process.HandleTable.GetObject(handle); - - if (thread == null) - { - return KernelResult.InvalidHandle; - } - - if (thread.Owner != currentProcess) - { - return KernelResult.InvalidHandle; - } - - if (currentThread == thread) - { - return KernelResult.InvalidThread; - } - - MemoryManager memory = currentProcess.CpuMemory; - - memory.Write(address + 0x0, thread.Context.GetX(0)); - memory.Write(address + 0x8, thread.Context.GetX(1)); - memory.Write(address + 0x10, thread.Context.GetX(2)); - memory.Write(address + 0x18, thread.Context.GetX(3)); - memory.Write(address + 0x20, thread.Context.GetX(4)); - memory.Write(address + 0x28, thread.Context.GetX(5)); - memory.Write(address + 0x30, thread.Context.GetX(6)); - memory.Write(address + 0x38, thread.Context.GetX(7)); - memory.Write(address + 0x40, thread.Context.GetX(8)); - memory.Write(address + 0x48, thread.Context.GetX(9)); - memory.Write(address + 0x50, thread.Context.GetX(10)); - memory.Write(address + 0x58, thread.Context.GetX(11)); - memory.Write(address + 0x60, thread.Context.GetX(12)); - memory.Write(address + 0x68, thread.Context.GetX(13)); - memory.Write(address + 0x70, thread.Context.GetX(14)); - memory.Write(address + 0x78, thread.Context.GetX(15)); - memory.Write(address + 0x80, thread.Context.GetX(16)); - memory.Write(address + 0x88, thread.Context.GetX(17)); - memory.Write(address + 0x90, thread.Context.GetX(18)); - memory.Write(address + 0x98, thread.Context.GetX(19)); - memory.Write(address + 0xa0, thread.Context.GetX(20)); - memory.Write(address + 0xa8, thread.Context.GetX(21)); - memory.Write(address + 0xb0, thread.Context.GetX(22)); - memory.Write(address + 0xb8, thread.Context.GetX(23)); - memory.Write(address + 0xc0, thread.Context.GetX(24)); - memory.Write(address + 0xc8, thread.Context.GetX(25)); - memory.Write(address + 0xd0, thread.Context.GetX(26)); - memory.Write(address + 0xd8, thread.Context.GetX(27)); - memory.Write(address + 0xe0, thread.Context.GetX(28)); - memory.Write(address + 0xe8, thread.Context.GetX(29)); - memory.Write(address + 0xf0, thread.Context.GetX(30)); - memory.Write(address + 0xf8, thread.Context.GetX(31)); - - memory.Write(address + 0x100, thread.LastPc); - - memory.Write(address + 0x108, (ulong)GetPsr(thread.Context)); - - memory.Write(address + 0x110, thread.Context.GetV(0)); - memory.Write(address + 0x120, thread.Context.GetV(1)); - memory.Write(address + 0x130, thread.Context.GetV(2)); - memory.Write(address + 0x140, thread.Context.GetV(3)); - memory.Write(address + 0x150, thread.Context.GetV(4)); - memory.Write(address + 0x160, thread.Context.GetV(5)); - memory.Write(address + 0x170, thread.Context.GetV(6)); - memory.Write(address + 0x180, thread.Context.GetV(7)); - memory.Write(address + 0x190, thread.Context.GetV(8)); - memory.Write(address + 0x1a0, thread.Context.GetV(9)); - memory.Write(address + 0x1b0, thread.Context.GetV(10)); - memory.Write(address + 0x1c0, thread.Context.GetV(11)); - memory.Write(address + 0x1d0, thread.Context.GetV(12)); - memory.Write(address + 0x1e0, thread.Context.GetV(13)); - memory.Write(address + 0x1f0, thread.Context.GetV(14)); - memory.Write(address + 0x200, thread.Context.GetV(15)); - memory.Write(address + 0x210, thread.Context.GetV(16)); - memory.Write(address + 0x220, thread.Context.GetV(17)); - memory.Write(address + 0x230, thread.Context.GetV(18)); - memory.Write(address + 0x240, thread.Context.GetV(19)); - memory.Write(address + 0x250, thread.Context.GetV(20)); - memory.Write(address + 0x260, thread.Context.GetV(21)); - memory.Write(address + 0x270, thread.Context.GetV(22)); - memory.Write(address + 0x280, thread.Context.GetV(23)); - memory.Write(address + 0x290, thread.Context.GetV(24)); - memory.Write(address + 0x2a0, thread.Context.GetV(25)); - memory.Write(address + 0x2b0, thread.Context.GetV(26)); - memory.Write(address + 0x2c0, thread.Context.GetV(27)); - memory.Write(address + 0x2d0, thread.Context.GetV(28)); - memory.Write(address + 0x2e0, thread.Context.GetV(29)); - memory.Write(address + 0x2f0, thread.Context.GetV(30)); - memory.Write(address + 0x300, thread.Context.GetV(31)); - - memory.Write(address + 0x310, (int)thread.Context.Fpcr); - memory.Write(address + 0x314, (int)thread.Context.Fpsr); - memory.Write(address + 0x318, thread.Context.Tpidr); - - return KernelResult.Success; - } - - private static int GetPsr(ExecutionContext context) - { - return (context.GetPstateFlag(PState.NFlag) ? (1 << 31) : 0) | - (context.GetPstateFlag(PState.ZFlag) ? (1 << 30) : 0) | - (context.GetPstateFlag(PState.CFlag) ? (1 << 29) : 0) | - (context.GetPstateFlag(PState.VFlag) ? (1 << 28) : 0); - } - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThreadSync.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThreadSync.cs deleted file mode 100644 index eecafb0b3..000000000 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThreadSync.cs +++ /dev/null @@ -1,306 +0,0 @@ -using Ryujinx.HLE.HOS.Kernel.Common; -using Ryujinx.HLE.HOS.Kernel.Process; -using Ryujinx.HLE.HOS.Kernel.Threading; -using System.Collections.Generic; - -namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall -{ - partial class SvcHandler - { - public KernelResult WaitSynchronization64([R(1)] ulong handlesPtr, [R(2)] int handlesCount, [R(3)] long timeout, [R(1)] out int handleIndex) - { - return WaitSynchronization(handlesPtr, handlesCount, timeout, out handleIndex); - } - - public KernelResult WaitSynchronization32( - [R(0)] uint timeoutLow, - [R(1)] uint handlesPtr, - [R(2)] int handlesCount, - [R(3)] uint timeoutHigh, - [R(1)] out int handleIndex) - { - long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32)); - - return WaitSynchronization(handlesPtr, handlesCount, timeout, out handleIndex); - } - - private KernelResult WaitSynchronization(ulong handlesPtr, int handlesCount, long timeout, out int handleIndex) - { - handleIndex = 0; - - if ((uint)handlesCount > 0x40) - { - return KernelResult.MaximumExceeded; - } - - List syncObjs = new List(); - - for (int index = 0; index < handlesCount; index++) - { - int handle = _process.CpuMemory.Read(handlesPtr + (ulong)index * 4); - - KSynchronizationObject syncObj = _process.HandleTable.GetObject(handle); - - if (syncObj == null) - { - break; - } - - syncObjs.Add(syncObj); - } - - return _system.Synchronization.WaitFor(syncObjs.ToArray(), timeout, out handleIndex); - } - - public KernelResult CancelSynchronization64([R(0)] int handle) - { - return CancelSynchronization(handle); - } - - public KernelResult CancelSynchronization32([R(0)] int handle) - { - return CancelSynchronization(handle); - } - - private KernelResult CancelSynchronization(int handle) - { - KThread thread = _process.HandleTable.GetKThread(handle); - - if (thread == null) - { - return KernelResult.InvalidHandle; - } - - thread.CancelSynchronization(); - - return KernelResult.Success; - } - - public KernelResult ArbitrateLock64([R(0)] int ownerHandle, [R(1)] ulong mutexAddress, [R(2)] int requesterHandle) - { - return ArbitrateLock(ownerHandle, mutexAddress, requesterHandle); - } - - public KernelResult ArbitrateLock32([R(0)] int ownerHandle, [R(1)] uint mutexAddress, [R(2)] int requesterHandle) - { - return ArbitrateLock(ownerHandle, mutexAddress, requesterHandle); - } - - private KernelResult ArbitrateLock(int ownerHandle, ulong mutexAddress, int requesterHandle) - { - if (IsPointingInsideKernel(mutexAddress)) - { - return KernelResult.InvalidMemState; - } - - if (IsAddressNotWordAligned(mutexAddress)) - { - return KernelResult.InvalidAddress; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - return currentProcess.AddressArbiter.ArbitrateLock(ownerHandle, mutexAddress, requesterHandle); - } - - public KernelResult ArbitrateUnlock64([R(0)] ulong mutexAddress) - { - return ArbitrateUnlock(mutexAddress); - } - - public KernelResult ArbitrateUnlock32([R(0)] uint mutexAddress) - { - return ArbitrateUnlock(mutexAddress); - } - - private KernelResult ArbitrateUnlock(ulong mutexAddress) - { - if (IsPointingInsideKernel(mutexAddress)) - { - return KernelResult.InvalidMemState; - } - - if (IsAddressNotWordAligned(mutexAddress)) - { - return KernelResult.InvalidAddress; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - return currentProcess.AddressArbiter.ArbitrateUnlock(mutexAddress); - } - - public KernelResult WaitProcessWideKeyAtomic64( - [R(0)] ulong mutexAddress, - [R(1)] ulong condVarAddress, - [R(2)] int handle, - [R(3)] long timeout) - { - return WaitProcessWideKeyAtomic(mutexAddress, condVarAddress, handle, timeout); - } - - public KernelResult WaitProcessWideKeyAtomic32( - [R(0)] uint mutexAddress, - [R(1)] uint condVarAddress, - [R(2)] int handle, - [R(3)] uint timeoutLow, - [R(4)] uint timeoutHigh) - { - long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32)); - - return WaitProcessWideKeyAtomic(mutexAddress, condVarAddress, handle, timeout); - } - - private KernelResult WaitProcessWideKeyAtomic( - ulong mutexAddress, - ulong condVarAddress, - int handle, - long timeout) - { - if (IsPointingInsideKernel(mutexAddress)) - { - return KernelResult.InvalidMemState; - } - - if (IsAddressNotWordAligned(mutexAddress)) - { - return KernelResult.InvalidAddress; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - return currentProcess.AddressArbiter.WaitProcessWideKeyAtomic( - mutexAddress, - condVarAddress, - handle, - timeout); - } - - public KernelResult SignalProcessWideKey64([R(0)] ulong address, [R(1)] int count) - { - return SignalProcessWideKey(address, count); - } - - public KernelResult SignalProcessWideKey32([R(0)] uint address, [R(1)] int count) - { - return SignalProcessWideKey(address, count); - } - - private KernelResult SignalProcessWideKey(ulong address, int count) - { - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - currentProcess.AddressArbiter.SignalProcessWideKey(address, count); - - return KernelResult.Success; - } - - public KernelResult WaitForAddress64([R(0)] ulong address, [R(1)] ArbitrationType type, [R(2)] int value, [R(3)] long timeout) - { - return WaitForAddress(address, type, value, timeout); - } - - public KernelResult WaitForAddress32([R(0)] uint address, [R(1)] ArbitrationType type, [R(2)] int value, [R(3)] uint timeoutLow, [R(4)] uint timeoutHigh) - { - long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32)); - - return WaitForAddress(address, type, value, timeout); - } - - private KernelResult WaitForAddress(ulong address, ArbitrationType type, int value, long timeout) - { - if (IsPointingInsideKernel(address)) - { - return KernelResult.InvalidMemState; - } - - if (IsAddressNotWordAligned(address)) - { - return KernelResult.InvalidAddress; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - KernelResult result; - - switch (type) - { - case ArbitrationType.WaitIfLessThan: - result = currentProcess.AddressArbiter.WaitForAddressIfLessThan(address, value, false, timeout); - break; - - case ArbitrationType.DecrementAndWaitIfLessThan: - result = currentProcess.AddressArbiter.WaitForAddressIfLessThan(address, value, true, timeout); - break; - - case ArbitrationType.WaitIfEqual: - result = currentProcess.AddressArbiter.WaitForAddressIfEqual(address, value, timeout); - break; - - default: - result = KernelResult.InvalidEnumValue; - break; - } - - return result; - } - - public KernelResult SignalToAddress64([R(0)] ulong address, [R(1)] SignalType type, [R(2)] int value, [R(3)] int count) - { - return SignalToAddress(address, type, value, count); - } - - public KernelResult SignalToAddress32([R(0)] uint address, [R(1)] SignalType type, [R(2)] int value, [R(3)] int count) - { - return SignalToAddress(address, type, value, count); - } - - private KernelResult SignalToAddress(ulong address, SignalType type, int value, int count) - { - if (IsPointingInsideKernel(address)) - { - return KernelResult.InvalidMemState; - } - - if (IsAddressNotWordAligned(address)) - { - return KernelResult.InvalidAddress; - } - - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); - - KernelResult result; - - switch (type) - { - case SignalType.Signal: - result = currentProcess.AddressArbiter.Signal(address, count); - break; - - case SignalType.SignalAndIncrementIfEqual: - result = currentProcess.AddressArbiter.SignalAndIncrementIfEqual(address, value, count); - break; - - case SignalType.SignalAndModifyIfEqual: - result = currentProcess.AddressArbiter.SignalAndModifyIfEqual(address, value, count); - break; - - default: - result = KernelResult.InvalidEnumValue; - break; - } - - return result; - } - - private bool IsPointingInsideKernel(ulong address) - { - return (address + 0x1000000000) < 0xffffff000; - } - - private bool IsAddressNotWordAligned(ulong address) - { - return (address & 3) != 0; - } - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs new file mode 100644 index 000000000..a0a15fcf4 --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs @@ -0,0 +1,2090 @@ +using ARMeilleure.Memory; +using Ryujinx.Common; +using Ryujinx.Common.Logging; +using Ryujinx.Cpu; +using Ryujinx.HLE.Exceptions; +using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Ipc; +using Ryujinx.HLE.HOS.Kernel.Memory; +using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.HLE.HOS.Kernel.Threading; +using System.Collections.Generic; +using System.Threading; + +namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall +{ + class Syscall + { + private readonly Switch _device; + private readonly KernelContext _context; + + public Syscall(Switch device, KernelContext context) + { + _device = device; + _context = context; + } + + // IPC + + private struct HleIpcMessage + { + public KProcess Process { get; } + public KThread Thread { get; } + public KClientSession Session { get; } + public IpcMessage Message { get; } + public long MessagePtr { get; } + + public HleIpcMessage( + KProcess process, + KThread thread, + KClientSession session, + IpcMessage message, + long messagePtr) + { + Process = process; + Thread = thread; + Session = session; + Message = message; + MessagePtr = messagePtr; + } + } + + public KernelResult ConnectToNamedPort(ulong namePtr, out int handle) + { + handle = 0; + + if (!KernelTransfer.UserToKernelString(_context, namePtr, 12, out string name)) + { + return KernelResult.UserCopyFailed; + } + + if (name.Length > 11) + { + return KernelResult.MaximumExceeded; + } + + KAutoObject autoObj = KAutoObject.FindNamedObject(_context, name); + + if (!(autoObj is KClientPort clientPort)) + { + return KernelResult.NotFound; + } + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + KernelResult result = currentProcess.HandleTable.ReserveHandle(out handle); + + if (result != KernelResult.Success) + { + return result; + } + + result = clientPort.Connect(out KClientSession clientSession); + + if (result != KernelResult.Success) + { + currentProcess.HandleTable.CancelHandleReservation(handle); + + return result; + } + + currentProcess.HandleTable.SetReservedHandleObj(handle, clientSession); + + clientSession.DecrementReferenceCount(); + + return result; + } + + public KernelResult SendSyncRequest(int handle) + { + return SendSyncRequestWithUserBuffer((ulong)_context.Scheduler.GetCurrentThread().Context.Tpidr, 0x100, handle); + } + + public KernelResult SendSyncRequestWithUserBuffer(ulong messagePtr, ulong size, int handle) + { + KProcess process = _context.Scheduler.GetCurrentProcess(); + + byte[] messageData = new byte[size]; + + process.CpuMemory.Read(messagePtr, messageData); + + KClientSession clientSession = process.HandleTable.GetObject(handle); + + if (clientSession == null || clientSession.Service == null) + { + return SendSyncRequest_(handle); + } + + if (clientSession != null) + { + _context.CriticalSection.Enter(); + + KThread currentThread = _context.Scheduler.GetCurrentThread(); + + currentThread.SignaledObj = null; + currentThread.ObjSyncResult = KernelResult.Success; + + currentThread.Reschedule(ThreadSchedState.Paused); + + IpcMessage message = new IpcMessage(messageData, (long)messagePtr); + + ThreadPool.QueueUserWorkItem(ProcessIpcRequest, new HleIpcMessage( + process, + currentThread, + clientSession, + message, + (long)messagePtr)); + + _context.ThreadCounter.AddCount(); + + _context.CriticalSection.Leave(); + + return currentThread.ObjSyncResult; + } + else + { + Logger.PrintWarning(LogClass.KernelSvc, $"Invalid session handle 0x{handle:x8}!"); + + return KernelResult.InvalidHandle; + } + } + + private void ProcessIpcRequest(object state) + { + HleIpcMessage ipcMessage = (HleIpcMessage)state; + + ipcMessage.Thread.ObjSyncResult = IpcHandler.IpcCall( + _device, + ipcMessage.Process, + ipcMessage.Process.CpuMemory, + ipcMessage.Thread, + ipcMessage.Session, + ipcMessage.Message, + ipcMessage.MessagePtr); + + _context.ThreadCounter.Signal(); + + ipcMessage.Thread.Reschedule(ThreadSchedState.Running); + } + + private KernelResult SendSyncRequest_(int handle) + { + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + KClientSession session = currentProcess.HandleTable.GetObject(handle); + + if (session == null) + { + return KernelResult.InvalidHandle; + } + + return session.SendSyncRequest(); + } + + public KernelResult CreateSession( + bool isLight, + ulong namePtr, + out int serverSessionHandle, + out int clientSessionHandle) + { + serverSessionHandle = 0; + clientSessionHandle = 0; + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + KResourceLimit resourceLimit = currentProcess.ResourceLimit; + + if (resourceLimit != null && !resourceLimit.Reserve(LimitableResource.Session, 1)) + { + return KernelResult.ResLimitExceeded; + } + + KernelResult result; + + if (isLight) + { + KLightSession session = new KLightSession(_context); + + result = currentProcess.HandleTable.GenerateHandle(session.ServerSession, out serverSessionHandle); + + if (result == KernelResult.Success) + { + result = currentProcess.HandleTable.GenerateHandle(session.ClientSession, out clientSessionHandle); + + if (result != KernelResult.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 == KernelResult.Success) + { + result = currentProcess.HandleTable.GenerateHandle(session.ClientSession, out clientSessionHandle); + + if (result != KernelResult.Success) + { + currentProcess.HandleTable.CloseHandle(serverSessionHandle); + + serverSessionHandle = 0; + } + } + + session.ServerSession.DecrementReferenceCount(); + session.ClientSession.DecrementReferenceCount(); + } + + return result; + } + + public KernelResult AcceptSession(int portHandle, out int sessionHandle) + { + sessionHandle = 0; + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + KServerPort serverPort = currentProcess.HandleTable.GetObject(portHandle); + + if (serverPort == null) + { + return KernelResult.InvalidHandle; + } + + KernelResult result = currentProcess.HandleTable.ReserveHandle(out int handle); + + if (result != KernelResult.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 = KernelResult.Success; + } + else + { + currentProcess.HandleTable.CancelHandleReservation(handle); + + result = KernelResult.NotFound; + } + + return result; + } + + public KernelResult ReplyAndReceive( + ulong handlesPtr, + int handlesCount, + int replyTargetHandle, + long timeout, + out int handleIndex) + { + handleIndex = 0; + + if ((uint)handlesCount > 0x40) + { + return KernelResult.MaximumExceeded; + } + + KProcess currentProcess = _context.Scheduler.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.UserToKernelInt32Array(_context, handlesPtr, handles)) + { + return KernelResult.UserCopyFailed; + } + + KSynchronizationObject[] syncObjs = new KSynchronizationObject[handlesCount]; + + for (int index = 0; index < handlesCount; index++) + { + KSynchronizationObject obj = currentProcess.HandleTable.GetObject(handles[index]); + + if (obj == null) + { + return KernelResult.InvalidHandle; + } + + syncObjs[index] = obj; + } + + KernelResult result; + + if (replyTargetHandle != 0) + { + KServerSession replyTarget = currentProcess.HandleTable.GetObject(replyTargetHandle); + + if (replyTarget == null) + { + return KernelResult.InvalidHandle; + } + + result = replyTarget.Reply(); + + if (result != KernelResult.Success) + { + return result; + } + } + + while ((result = _context.Synchronization.WaitFor(syncObjs, timeout, out handleIndex)) == KernelResult.Success) + { + KServerSession session = currentProcess.HandleTable.GetObject(handles[handleIndex]); + + if (session == null) + { + break; + } + + if ((result = session.Receive()) != KernelResult.NotFound) + { + break; + } + } + + return result; + } + + public KernelResult CreatePort( + int maxSessions, + bool isLight, + ulong namePtr, + out int serverPortHandle, + out int clientPortHandle) + { + serverPortHandle = clientPortHandle = 0; + + if (maxSessions < 1) + { + return KernelResult.MaximumExceeded; + } + + KPort port = new KPort(_context, maxSessions, isLight, (long)namePtr); + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + KernelResult result = currentProcess.HandleTable.GenerateHandle(port.ClientPort, out clientPortHandle); + + if (result != KernelResult.Success) + { + return result; + } + + result = currentProcess.HandleTable.GenerateHandle(port.ServerPort, out serverPortHandle); + + if (result != KernelResult.Success) + { + currentProcess.HandleTable.CloseHandle(clientPortHandle); + } + + return result; + } + + public KernelResult ManageNamedPort(ulong namePtr, int maxSessions, out int handle) + { + handle = 0; + + if (!KernelTransfer.UserToKernelString(_context, namePtr, 12, out string name)) + { + return KernelResult.UserCopyFailed; + } + + if (maxSessions < 0 || name.Length > 11) + { + return KernelResult.MaximumExceeded; + } + + if (maxSessions == 0) + { + return KAutoObject.RemoveName(_context, name); + } + + KPort port = new KPort(_context, maxSessions, false, 0); + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + KernelResult result = currentProcess.HandleTable.GenerateHandle(port.ServerPort, out handle); + + if (result != KernelResult.Success) + { + return result; + } + + result = port.ClientPort.SetName(name); + + if (result != KernelResult.Success) + { + currentProcess.HandleTable.CloseHandle(handle); + } + + return result; + } + + public KernelResult ConnectToPort(int clientPortHandle, out int clientSessionHandle) + { + clientSessionHandle = 0; + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + KClientPort clientPort = currentProcess.HandleTable.GetObject(clientPortHandle); + + if (clientPort == null) + { + return KernelResult.InvalidHandle; + } + + KernelResult result = currentProcess.HandleTable.ReserveHandle(out int handle); + + if (result != KernelResult.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 != KernelResult.Success) + { + currentProcess.HandleTable.CancelHandleReservation(handle); + + return result; + } + + currentProcess.HandleTable.SetReservedHandleObj(handle, session); + + session.DecrementReferenceCount(); + + clientSessionHandle = handle; + + return result; + } + + // Memory + + public KernelResult SetHeapSize(ulong size, out ulong position) + { + if ((size & 0xfffffffe001fffff) != 0) + { + position = 0; + + return KernelResult.InvalidSize; + } + + KProcess process = _context.Scheduler.GetCurrentProcess(); + + return process.MemoryManager.SetHeapSize(size, out position); + } + + public KernelResult SetMemoryAttribute( + ulong position, + ulong size, + MemoryAttribute attributeMask, + MemoryAttribute attributeValue) + { + if (!PageAligned(position)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + MemoryAttribute attributes = attributeMask | attributeValue; + + if (attributes != attributeMask || + (attributes | MemoryAttribute.Uncached) != MemoryAttribute.Uncached) + { + return KernelResult.InvalidCombination; + } + + KProcess process = _context.Scheduler.GetCurrentProcess(); + + KernelResult result = process.MemoryManager.SetMemoryAttribute( + position, + size, + attributeMask, + attributeValue); + + return result; + } + + public KernelResult MapMemory(ulong dst, ulong src, ulong size) + { + if (!PageAligned(src | dst)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (src + size <= src || dst + size <= dst) + { + return KernelResult.InvalidMemState; + } + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + if (!currentProcess.MemoryManager.InsideAddrSpace(src, size)) + { + return KernelResult.InvalidMemState; + } + + if (currentProcess.MemoryManager.OutsideStackRegion(dst, size) || + currentProcess.MemoryManager.InsideHeapRegion(dst, size) || + currentProcess.MemoryManager.InsideAliasRegion(dst, size)) + { + return KernelResult.InvalidMemRange; + } + + KProcess process = _context.Scheduler.GetCurrentProcess(); + + return process.MemoryManager.Map(dst, src, size); + } + + public KernelResult UnmapMemory(ulong dst, ulong src, ulong size) + { + if (!PageAligned(src | dst)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (src + size <= src || dst + size <= dst) + { + return KernelResult.InvalidMemState; + } + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + if (!currentProcess.MemoryManager.InsideAddrSpace(src, size)) + { + return KernelResult.InvalidMemState; + } + + if (currentProcess.MemoryManager.OutsideStackRegion(dst, size) || + currentProcess.MemoryManager.InsideHeapRegion(dst, size) || + currentProcess.MemoryManager.InsideAliasRegion(dst, size)) + { + return KernelResult.InvalidMemRange; + } + + KProcess process = _context.Scheduler.GetCurrentProcess(); + + return process.MemoryManager.Unmap(dst, src, size); + } + + public KernelResult QueryMemory(ulong infoPtr, ulong position, out ulong pageInfo) + { + KProcess process = _context.Scheduler.GetCurrentProcess(); + + KMemoryInfo blkInfo = process.MemoryManager.QueryMemory(position); + + process.CpuMemory.Write(infoPtr + 0x00, blkInfo.Address); + process.CpuMemory.Write(infoPtr + 0x08, blkInfo.Size); + process.CpuMemory.Write(infoPtr + 0x10, (int)blkInfo.State & 0xff); + process.CpuMemory.Write(infoPtr + 0x14, (int)blkInfo.Attribute); + process.CpuMemory.Write(infoPtr + 0x18, (int)blkInfo.Permission); + process.CpuMemory.Write(infoPtr + 0x1c, blkInfo.IpcRefCount); + process.CpuMemory.Write(infoPtr + 0x20, blkInfo.DeviceRefCount); + process.CpuMemory.Write(infoPtr + 0x24, 0); + + pageInfo = 0; + + return KernelResult.Success; + } + + public KernelResult MapSharedMemory(int handle, ulong address, ulong size, MemoryPermission permission) + { + if (!PageAligned(address)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (address + size <= address) + { + return KernelResult.InvalidMemState; + } + + if ((permission | MemoryPermission.Write) != MemoryPermission.ReadAndWrite) + { + return KernelResult.InvalidPermission; + } + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + KSharedMemory sharedMemory = currentProcess.HandleTable.GetObject(handle); + + if (sharedMemory == null) + { + return KernelResult.InvalidHandle; + } + + if (currentProcess.MemoryManager.IsInvalidRegion(address, size) || + currentProcess.MemoryManager.InsideHeapRegion(address, size) || + currentProcess.MemoryManager.InsideAliasRegion(address, size)) + { + return KernelResult.InvalidMemRange; + } + + return sharedMemory.MapIntoProcess( + currentProcess.MemoryManager, + address, + size, + currentProcess, + permission); + } + + public KernelResult UnmapSharedMemory(int handle, ulong address, ulong size) + { + if (!PageAligned(address)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (address + size <= address) + { + return KernelResult.InvalidMemState; + } + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + KSharedMemory sharedMemory = currentProcess.HandleTable.GetObject(handle); + + if (sharedMemory == null) + { + return KernelResult.InvalidHandle; + } + + if (currentProcess.MemoryManager.IsInvalidRegion(address, size) || + currentProcess.MemoryManager.InsideHeapRegion(address, size) || + currentProcess.MemoryManager.InsideAliasRegion(address, size)) + { + return KernelResult.InvalidMemRange; + } + + return sharedMemory.UnmapFromProcess( + currentProcess.MemoryManager, + address, + size, + currentProcess); + } + + public KernelResult CreateTransferMemory(ulong address, ulong size, MemoryPermission permission, out int handle) + { + handle = 0; + + if (!PageAligned(address)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (address + size <= address) + { + return KernelResult.InvalidMemState; + } + + if (permission > MemoryPermission.ReadAndWrite || permission == MemoryPermission.Write) + { + return KernelResult.InvalidPermission; + } + + KProcess process = _context.Scheduler.GetCurrentProcess(); + + KernelResult result = process.MemoryManager.ReserveTransferMemory(address, size, permission); + + if (result != KernelResult.Success) + { + return result; + } + + KTransferMemory transferMemory = new KTransferMemory(_context, address, size); + + return process.HandleTable.GenerateHandle(transferMemory, out handle); + } + + public KernelResult MapPhysicalMemory(ulong address, ulong size) + { + if (!PageAligned(address)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (address + size <= address) + { + return KernelResult.InvalidMemRange; + } + + KProcess currentProcess = _context.Scheduler.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 = _context.Scheduler.GetCurrentProcess(); + + return process.MemoryManager.MapPhysicalMemory(address, size); + } + + public KernelResult UnmapPhysicalMemory(ulong address, ulong size) + { + if (!PageAligned(address)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (address + size <= address) + { + return KernelResult.InvalidMemRange; + } + + KProcess currentProcess = _context.Scheduler.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 = _context.Scheduler.GetCurrentProcess(); + + return process.MemoryManager.UnmapPhysicalMemory(address, size); + } + + public KernelResult 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 = _context.Scheduler.GetCurrentProcess(); + + KProcess targetProcess = currentProcess.HandleTable.GetObject(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); + } + + public KernelResult 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 = _context.Scheduler.GetCurrentProcess(); + + KProcess targetProcess = currentProcess.HandleTable.GetObject(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); + } + + public KernelResult SetProcessMemoryPermission(int handle, ulong src, ulong size, MemoryPermission permission) + { + if (!PageAligned(src)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (permission != MemoryPermission.None && + permission != MemoryPermission.Read && + permission != MemoryPermission.ReadAndWrite && + permission != MemoryPermission.ReadAndExecute) + { + return KernelResult.InvalidPermission; + } + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + KProcess targetProcess = currentProcess.HandleTable.GetObject(handle); + + if (targetProcess == null) + { + return KernelResult.InvalidHandle; + } + + if (targetProcess.MemoryManager.OutsideAddrSpace(src, size)) + { + return KernelResult.InvalidMemState; + } + + return targetProcess.MemoryManager.SetProcessMemoryPermission(src, size, permission); + } + + private static bool PageAligned(ulong position) + { + return (position & (KMemoryManager.PageSize - 1)) == 0; + } + + // System + + public KernelResult TerminateProcess(int handle) + { + KProcess process = _context.Scheduler.GetCurrentProcess(); + + process = process.HandleTable.GetObject(handle); + + KernelResult result; + + if (process != null) + { + if (process == _context.Scheduler.GetCurrentProcess()) + { + result = KernelResult.Success; + process.DecrementToZeroWhileTerminatingCurrent(); + } + else + { + result = process.Terminate(); + process.DecrementReferenceCount(); + } + } + else + { + result = KernelResult.InvalidHandle; + } + + return result; + } + + public void ExitProcess() + { + _context.Scheduler.GetCurrentProcess().TerminateCurrentProcess(); + } + + public KernelResult SignalEvent(int handle) + { + KProcess process = _context.Scheduler.GetCurrentProcess(); + + KWritableEvent writableEvent = process.HandleTable.GetObject(handle); + + KernelResult result; + + if (writableEvent != null) + { + writableEvent.Signal(); + + result = KernelResult.Success; + } + else + { + result = KernelResult.InvalidHandle; + } + + return result; + } + + public KernelResult ClearEvent(int handle) + { + KernelResult result; + + KProcess process = _context.Scheduler.GetCurrentProcess(); + + KWritableEvent writableEvent = process.HandleTable.GetObject(handle); + + if (writableEvent == null) + { + KReadableEvent readableEvent = process.HandleTable.GetObject(handle); + + result = readableEvent?.Clear() ?? KernelResult.InvalidHandle; + } + else + { + result = writableEvent.Clear(); + } + + return result; + } + + public KernelResult CloseHandle(int handle) + { + KProcess process = _context.Scheduler.GetCurrentProcess(); + + KAutoObject obj = process.HandleTable.GetObject(handle); + + process.HandleTable.CloseHandle(handle); + + if (obj == null) + { + return KernelResult.InvalidHandle; + } + + if (obj is KSession session) + { + session.Dispose(); + } + else if (obj is KTransferMemory transferMemory) + { + process.MemoryManager.ResetTransferMemory( + transferMemory.Address, + transferMemory.Size); + } + + return KernelResult.Success; + } + + public KernelResult ResetSignal(int handle) + { + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + KReadableEvent readableEvent = currentProcess.HandleTable.GetObject(handle); + + KernelResult 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; + } + + public ulong GetSystemTick() + { + return _context.Scheduler.GetCurrentThread().Context.CntpctEl0; + } + + public KernelResult GetProcessId(int handle, out long pid) + { + KProcess currentProcess = _context.Scheduler.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 + ? KernelResult.Success + : KernelResult.InvalidHandle; + } + + public void Break(ulong reason) + { + KThread currentThread = _context.Scheduler.GetCurrentThread(); + + if ((reason & (1UL << 31)) == 0) + { + currentThread.PrintGuestStackTrace(); + + // 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.PrintInfo(LogClass.KernelSvc, "Debugger triggered."); + + currentThread.PrintGuestStackTrace(); + } + } + + public void OutputDebugString(ulong strPtr, ulong size) + { + KProcess process = _context.Scheduler.GetCurrentProcess(); + + string str = MemoryHelper.ReadAsciiString(process.CpuMemory, (long)strPtr, (long)size); + + Logger.PrintWarning(LogClass.KernelSvc, str); + } + + public KernelResult GetInfo(uint id, int handle, long subId, out long value) + { + value = 0; + + switch (id) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + case 20: + case 21: + case 22: + { + if (subId != 0) + { + return KernelResult.InvalidCombination; + } + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + KProcess process = currentProcess.HandleTable.GetKProcess(handle); + + if (process == null) + { + return KernelResult.InvalidHandle; + } + + switch (id) + { + case 0: value = process.Capabilities.AllowedCpuCoresMask; break; + case 1: value = process.Capabilities.AllowedThreadPriosMask; break; + + case 2: value = (long)process.MemoryManager.AliasRegionStart; break; + case 3: + value = (long)(process.MemoryManager.AliasRegionEnd - + process.MemoryManager.AliasRegionStart); break; + + case 4: value = (long)process.MemoryManager.HeapRegionStart; break; + case 5: + value = (long)(process.MemoryManager.HeapRegionEnd - + process.MemoryManager.HeapRegionStart); break; + + case 6: value = (long)process.GetMemoryCapacity(); break; + + case 7: value = (long)process.GetMemoryUsage(); break; + + case 12: value = (long)process.MemoryManager.GetAddrSpaceBaseAddr(); break; + + case 13: value = (long)process.MemoryManager.GetAddrSpaceSize(); break; + + case 14: value = (long)process.MemoryManager.StackRegionStart; break; + case 15: + value = (long)(process.MemoryManager.StackRegionEnd - + process.MemoryManager.StackRegionStart); break; + + case 16: value = (long)process.PersonalMmHeapPagesCount * KMemoryManager.PageSize; break; + + case 17: + if (process.PersonalMmHeapPagesCount != 0) + { + value = process.MemoryManager.GetMmUsedPages() * KMemoryManager.PageSize; + } + + break; + + case 18: value = (long)process.TitleId; break; + + case 20: value = (long)process.UserExceptionContextAddress; break; + + case 21: value = (long)process.GetMemoryCapacityWithoutPersonalMmHeap(); break; + + case 22: value = (long)process.GetMemoryUsageWithoutPersonalMmHeap(); break; + } + + break; + } + + case 8: + { + if (handle != 0) + { + return KernelResult.InvalidHandle; + } + + if (subId != 0) + { + return KernelResult.InvalidCombination; + } + + value = _context.Scheduler.GetCurrentProcess().Debug ? 1 : 0; + + break; + } + + case 9: + { + if (handle != 0) + { + return KernelResult.InvalidHandle; + } + + if (subId != 0) + { + return KernelResult.InvalidCombination; + } + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + if (currentProcess.ResourceLimit != null) + { + KHandleTable handleTable = currentProcess.HandleTable; + KResourceLimit resourceLimit = currentProcess.ResourceLimit; + + KernelResult result = handleTable.GenerateHandle(resourceLimit, out int resLimHandle); + + if (result != KernelResult.Success) + { + return result; + } + + value = (uint)resLimHandle; + } + + break; + } + + case 10: + { + if (handle != 0) + { + return KernelResult.InvalidHandle; + } + + int currentCore = _context.Scheduler.GetCurrentThread().CurrentCore; + + if (subId != -1 && subId != currentCore) + { + return KernelResult.InvalidCombination; + } + + value = _context.Scheduler.CoreContexts[currentCore].TotalIdleTimeTicks; + + break; + } + + case 11: + { + if (handle != 0) + { + return KernelResult.InvalidHandle; + } + + if ((ulong)subId > 3) + { + return KernelResult.InvalidCombination; + } + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + + value = currentProcess.RandomEntropy[subId]; + + break; + } + + case 0xf0000002u: + { + if (subId < -1 || subId > 3) + { + return KernelResult.InvalidCombination; + } + + KThread thread = _context.Scheduler.GetCurrentProcess().HandleTable.GetKThread(handle); + + if (thread == null) + { + return KernelResult.InvalidHandle; + } + + KThread currentThread = _context.Scheduler.GetCurrentThread(); + + int currentCore = currentThread.CurrentCore; + + if (subId != -1 && subId != currentCore) + { + return KernelResult.Success; + } + + KCoreContext coreContext = _context.Scheduler.CoreContexts[currentCore]; + + long timeDelta = PerformanceCounter.ElapsedMilliseconds - coreContext.LastContextSwitchTime; + + if (subId != -1) + { + value = KTimeManager.ConvertMillisecondsToTicks(timeDelta); + } + else + { + long totalTimeRunning = thread.TotalTimeRunning; + + if (thread == currentThread) + { + totalTimeRunning += timeDelta; + } + + value = KTimeManager.ConvertMillisecondsToTicks(totalTimeRunning); + } + + break; + } + + default: return KernelResult.InvalidEnumValue; + } + + return KernelResult.Success; + } + + public KernelResult CreateEvent(out int wEventHandle, out int rEventHandle) + { + KEvent Event = new KEvent(_context); + + KProcess process = _context.Scheduler.GetCurrentProcess(); + + KernelResult result = process.HandleTable.GenerateHandle(Event.WritableEvent, out wEventHandle); + + if (result == KernelResult.Success) + { + result = process.HandleTable.GenerateHandle(Event.ReadableEvent, out rEventHandle); + + if (result != KernelResult.Success) + { + process.HandleTable.CloseHandle(wEventHandle); + } + } + else + { + rEventHandle = 0; + } + + return result; + } + + public KernelResult GetProcessList(ulong address, int maxCount, out int count) + { + count = 0; + + if ((maxCount >> 28) != 0) + { + return KernelResult.MaximumExceeded; + } + + if (maxCount != 0) + { + KProcess currentProcess = _context.Scheduler.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.KernelToUserInt64(_context, address + (ulong)copyCount * 8, process.Pid)) + { + return KernelResult.UserCopyFailed; + } + } + + copyCount++; + } + } + + count = copyCount; + + return KernelResult.Success; + } + + public KernelResult GetSystemInfo(uint id, int handle, long subId, out long value) + { + 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.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 * KMemoryManager.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 KernelResult.Success; + } + + // Thread + + public KernelResult CreateThread( + ulong entrypoint, + ulong argsPtr, + ulong stackTop, + int priority, + int cpuCore, + out int handle) + { + handle = 0; + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + if (cpuCore == -2) + { + cpuCore = currentProcess.DefaultCpuCore; + } + + if ((uint)cpuCore >= KScheduler.CpuCoresCount || !currentProcess.IsCpuCoreAllowed(cpuCore)) + { + return KernelResult.InvalidCpuCore; + } + + if ((uint)priority >= KScheduler.PrioritiesCount || !currentProcess.IsPriorityAllowed(priority)) + { + return KernelResult.InvalidPriority; + } + + long timeout = KTimeManager.ConvertMillisecondsToNanoseconds(100); + + if (currentProcess.ResourceLimit != null && + !currentProcess.ResourceLimit.Reserve(LimitableResource.Thread, 1, timeout)) + { + return KernelResult.ResLimitExceeded; + } + + KThread thread = new KThread(_context); + + KernelResult result = currentProcess.InitializeThread( + thread, + entrypoint, + argsPtr, + stackTop, + priority, + cpuCore); + + if (result == KernelResult.Success) + { + KProcess process = _context.Scheduler.GetCurrentProcess(); + + result = process.HandleTable.GenerateHandle(thread, out handle); + } + else + { + currentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1); + } + + thread.DecrementReferenceCount(); + + return result; + } + + public KernelResult StartThread(int handle) + { + KProcess process = _context.Scheduler.GetCurrentProcess(); + + KThread thread = process.HandleTable.GetKThread(handle); + + if (thread != null) + { + thread.IncrementReferenceCount(); + + KernelResult result = thread.Start(); + + if (result == KernelResult.Success) + { + thread.IncrementReferenceCount(); + } + + thread.DecrementReferenceCount(); + + return result; + } + else + { + return KernelResult.InvalidHandle; + } + } + + public void ExitThread() + { + KThread currentThread = _context.Scheduler.GetCurrentThread(); + + _context.Scheduler.ExitThread(currentThread); + + currentThread.Exit(); + } + + public void SleepThread(long timeout) + { + KThread currentThread = _context.Scheduler.GetCurrentThread(); + + if (timeout < 1) + { + switch (timeout) + { + case 0: currentThread.Yield(); break; + case -1: currentThread.YieldWithLoadBalancing(); break; + case -2: currentThread.YieldAndWaitForLoadBalancing(); break; + } + } + else + { + currentThread.Sleep(timeout); + } + } + + public KernelResult GetThreadPriority(int handle, out int priority) + { + KProcess process = _context.Scheduler.GetCurrentProcess(); + + KThread thread = process.HandleTable.GetKThread(handle); + + if (thread != null) + { + priority = thread.DynamicPriority; + + return KernelResult.Success; + } + else + { + priority = 0; + + return KernelResult.InvalidHandle; + } + } + + public KernelResult SetThreadPriority(int handle, int priority) + { + // TODO: NPDM check. + + KProcess process = _context.Scheduler.GetCurrentProcess(); + + KThread thread = process.HandleTable.GetKThread(handle); + + if (thread == null) + { + return KernelResult.InvalidHandle; + } + + thread.SetPriority(priority); + + return KernelResult.Success; + } + + public KernelResult GetThreadCoreMask(int handle, out int preferredCore, out long affinityMask) + { + KProcess process = _context.Scheduler.GetCurrentProcess(); + + KThread thread = process.HandleTable.GetKThread(handle); + + if (thread != null) + { + preferredCore = thread.PreferredCore; + affinityMask = thread.AffinityMask; + + return KernelResult.Success; + } + else + { + preferredCore = 0; + affinityMask = 0; + + return KernelResult.InvalidHandle; + } + } + + public KernelResult SetThreadCoreMask(int handle, int preferredCore, long affinityMask) + { + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + if (preferredCore == -2) + { + preferredCore = currentProcess.DefaultCpuCore; + + affinityMask = 1 << preferredCore; + } + else + { + if ((currentProcess.Capabilities.AllowedCpuCoresMask | affinityMask) != + currentProcess.Capabilities.AllowedCpuCoresMask) + { + return KernelResult.InvalidCpuCore; + } + + if (affinityMask == 0) + { + return KernelResult.InvalidCombination; + } + + if ((uint)preferredCore > 3) + { + if ((preferredCore | 2) != -1) + { + return KernelResult.InvalidCpuCore; + } + } + else if ((affinityMask & (1 << preferredCore)) == 0) + { + return KernelResult.InvalidCombination; + } + } + + KProcess process = _context.Scheduler.GetCurrentProcess(); + + KThread thread = process.HandleTable.GetKThread(handle); + + if (thread == null) + { + return KernelResult.InvalidHandle; + } + + return thread.SetCoreAndAffinityMask(preferredCore, affinityMask); + } + + public int GetCurrentProcessorNumber() + { + return _context.Scheduler.GetCurrentThread().CurrentCore; + } + + public KernelResult GetThreadId(int handle, out long threadUid) + { + KProcess process = _context.Scheduler.GetCurrentProcess(); + + KThread thread = process.HandleTable.GetKThread(handle); + + if (thread != null) + { + threadUid = thread.ThreadUid; + + return KernelResult.Success; + } + else + { + threadUid = 0; + + return KernelResult.InvalidHandle; + } + } + + public KernelResult SetThreadActivity(int handle, bool pause) + { + KProcess process = _context.Scheduler.GetCurrentProcess(); + + KThread thread = process.HandleTable.GetObject(handle); + + if (thread == null) + { + return KernelResult.InvalidHandle; + } + + if (thread.Owner != process) + { + return KernelResult.InvalidHandle; + } + + if (thread == _context.Scheduler.GetCurrentThread()) + { + return KernelResult.InvalidThread; + } + + return thread.SetActivity(pause); + } + + public KernelResult GetThreadContext3(ulong address, int handle) + { + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + KThread currentThread = _context.Scheduler.GetCurrentThread(); + + KThread thread = currentProcess.HandleTable.GetObject(handle); + + if (thread == null) + { + return KernelResult.InvalidHandle; + } + + if (thread.Owner != currentProcess) + { + return KernelResult.InvalidHandle; + } + + if (currentThread == thread) + { + return KernelResult.InvalidThread; + } + + MemoryManager memory = currentProcess.CpuMemory; + + memory.Write(address + 0x0, thread.Context.GetX(0)); + memory.Write(address + 0x8, thread.Context.GetX(1)); + memory.Write(address + 0x10, thread.Context.GetX(2)); + memory.Write(address + 0x18, thread.Context.GetX(3)); + memory.Write(address + 0x20, thread.Context.GetX(4)); + memory.Write(address + 0x28, thread.Context.GetX(5)); + memory.Write(address + 0x30, thread.Context.GetX(6)); + memory.Write(address + 0x38, thread.Context.GetX(7)); + memory.Write(address + 0x40, thread.Context.GetX(8)); + memory.Write(address + 0x48, thread.Context.GetX(9)); + memory.Write(address + 0x50, thread.Context.GetX(10)); + memory.Write(address + 0x58, thread.Context.GetX(11)); + memory.Write(address + 0x60, thread.Context.GetX(12)); + memory.Write(address + 0x68, thread.Context.GetX(13)); + memory.Write(address + 0x70, thread.Context.GetX(14)); + memory.Write(address + 0x78, thread.Context.GetX(15)); + memory.Write(address + 0x80, thread.Context.GetX(16)); + memory.Write(address + 0x88, thread.Context.GetX(17)); + memory.Write(address + 0x90, thread.Context.GetX(18)); + memory.Write(address + 0x98, thread.Context.GetX(19)); + memory.Write(address + 0xa0, thread.Context.GetX(20)); + memory.Write(address + 0xa8, thread.Context.GetX(21)); + memory.Write(address + 0xb0, thread.Context.GetX(22)); + memory.Write(address + 0xb8, thread.Context.GetX(23)); + memory.Write(address + 0xc0, thread.Context.GetX(24)); + memory.Write(address + 0xc8, thread.Context.GetX(25)); + memory.Write(address + 0xd0, thread.Context.GetX(26)); + memory.Write(address + 0xd8, thread.Context.GetX(27)); + memory.Write(address + 0xe0, thread.Context.GetX(28)); + memory.Write(address + 0xe8, thread.Context.GetX(29)); + memory.Write(address + 0xf0, thread.Context.GetX(30)); + memory.Write(address + 0xf8, thread.Context.GetX(31)); + + memory.Write(address + 0x100, thread.LastPc); + + memory.Write(address + 0x108, (ulong)GetPsr(thread.Context)); + + memory.Write(address + 0x110, thread.Context.GetV(0)); + memory.Write(address + 0x120, thread.Context.GetV(1)); + memory.Write(address + 0x130, thread.Context.GetV(2)); + memory.Write(address + 0x140, thread.Context.GetV(3)); + memory.Write(address + 0x150, thread.Context.GetV(4)); + memory.Write(address + 0x160, thread.Context.GetV(5)); + memory.Write(address + 0x170, thread.Context.GetV(6)); + memory.Write(address + 0x180, thread.Context.GetV(7)); + memory.Write(address + 0x190, thread.Context.GetV(8)); + memory.Write(address + 0x1a0, thread.Context.GetV(9)); + memory.Write(address + 0x1b0, thread.Context.GetV(10)); + memory.Write(address + 0x1c0, thread.Context.GetV(11)); + memory.Write(address + 0x1d0, thread.Context.GetV(12)); + memory.Write(address + 0x1e0, thread.Context.GetV(13)); + memory.Write(address + 0x1f0, thread.Context.GetV(14)); + memory.Write(address + 0x200, thread.Context.GetV(15)); + memory.Write(address + 0x210, thread.Context.GetV(16)); + memory.Write(address + 0x220, thread.Context.GetV(17)); + memory.Write(address + 0x230, thread.Context.GetV(18)); + memory.Write(address + 0x240, thread.Context.GetV(19)); + memory.Write(address + 0x250, thread.Context.GetV(20)); + memory.Write(address + 0x260, thread.Context.GetV(21)); + memory.Write(address + 0x270, thread.Context.GetV(22)); + memory.Write(address + 0x280, thread.Context.GetV(23)); + memory.Write(address + 0x290, thread.Context.GetV(24)); + memory.Write(address + 0x2a0, thread.Context.GetV(25)); + memory.Write(address + 0x2b0, thread.Context.GetV(26)); + memory.Write(address + 0x2c0, thread.Context.GetV(27)); + memory.Write(address + 0x2d0, thread.Context.GetV(28)); + memory.Write(address + 0x2e0, thread.Context.GetV(29)); + memory.Write(address + 0x2f0, thread.Context.GetV(30)); + memory.Write(address + 0x300, thread.Context.GetV(31)); + + memory.Write(address + 0x310, (int)thread.Context.Fpcr); + memory.Write(address + 0x314, (int)thread.Context.Fpsr); + memory.Write(address + 0x318, thread.Context.Tpidr); + + return KernelResult.Success; + } + + private static int GetPsr(ARMeilleure.State.ExecutionContext context) + { + return (context.GetPstateFlag(ARMeilleure.State.PState.NFlag) ? (1 << 31) : 0) | + (context.GetPstateFlag(ARMeilleure.State.PState.ZFlag) ? (1 << 30) : 0) | + (context.GetPstateFlag(ARMeilleure.State.PState.CFlag) ? (1 << 29) : 0) | + (context.GetPstateFlag(ARMeilleure.State.PState.VFlag) ? (1 << 28) : 0); + } + + // Thread synchronization + + public KernelResult WaitSynchronization(ulong handlesPtr, int handlesCount, long timeout, out int handleIndex) + { + handleIndex = 0; + + if ((uint)handlesCount > 0x40) + { + return KernelResult.MaximumExceeded; + } + + List syncObjs = new List(); + + KProcess process = _context.Scheduler.GetCurrentProcess(); + + for (int index = 0; index < handlesCount; index++) + { + int handle = process.CpuMemory.Read(handlesPtr + (ulong)index * 4); + + KSynchronizationObject syncObj = process.HandleTable.GetObject(handle); + + if (syncObj == null) + { + break; + } + + syncObjs.Add(syncObj); + } + + return _context.Synchronization.WaitFor(syncObjs.ToArray(), timeout, out handleIndex); + } + + public KernelResult CancelSynchronization(int handle) + { + KProcess process = _context.Scheduler.GetCurrentProcess(); + + KThread thread = process.HandleTable.GetKThread(handle); + + if (thread == null) + { + return KernelResult.InvalidHandle; + } + + thread.CancelSynchronization(); + + return KernelResult.Success; + } + + public KernelResult ArbitrateLock(int ownerHandle, ulong mutexAddress, int requesterHandle) + { + if (IsPointingInsideKernel(mutexAddress)) + { + return KernelResult.InvalidMemState; + } + + if (IsAddressNotWordAligned(mutexAddress)) + { + return KernelResult.InvalidAddress; + } + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + return currentProcess.AddressArbiter.ArbitrateLock(ownerHandle, mutexAddress, requesterHandle); + } + + public KernelResult ArbitrateUnlock(ulong mutexAddress) + { + if (IsPointingInsideKernel(mutexAddress)) + { + return KernelResult.InvalidMemState; + } + + if (IsAddressNotWordAligned(mutexAddress)) + { + return KernelResult.InvalidAddress; + } + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + return currentProcess.AddressArbiter.ArbitrateUnlock(mutexAddress); + } + + public KernelResult WaitProcessWideKeyAtomic( + ulong mutexAddress, + ulong condVarAddress, + int handle, + long timeout) + { + if (IsPointingInsideKernel(mutexAddress)) + { + return KernelResult.InvalidMemState; + } + + if (IsAddressNotWordAligned(mutexAddress)) + { + return KernelResult.InvalidAddress; + } + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + return currentProcess.AddressArbiter.WaitProcessWideKeyAtomic( + mutexAddress, + condVarAddress, + handle, + timeout); + } + + public KernelResult SignalProcessWideKey(ulong address, int count) + { + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + currentProcess.AddressArbiter.SignalProcessWideKey(address, count); + + return KernelResult.Success; + } + + public KernelResult WaitForAddress(ulong address, ArbitrationType type, int value, long timeout) + { + if (IsPointingInsideKernel(address)) + { + return KernelResult.InvalidMemState; + } + + if (IsAddressNotWordAligned(address)) + { + return KernelResult.InvalidAddress; + } + + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); + + 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, + }; + } + + public KernelResult SignalToAddress(ulong address, SignalType type, int value, int count) + { + if (IsPointingInsideKernel(address)) + { + return KernelResult.InvalidMemState; + } + + if (IsAddressNotWordAligned(address)) + { + return KernelResult.InvalidAddress; + } + + KProcess currentProcess = _context.Scheduler.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 + }; + } + + private bool IsPointingInsideKernel(ulong address) + { + return (address + 0x1000000000) < 0xffffff000; + } + + private bool IsAddressNotWordAligned(ulong address) + { + return (address & 3) != 0; + } + } +} diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs new file mode 100644 index 000000000..d7cbcbf51 --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs @@ -0,0 +1,435 @@ +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Memory; +using Ryujinx.HLE.HOS.Kernel.Threading; + +namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall +{ + class Syscall32 + { + private readonly Syscall _syscall; + + public Syscall32(Syscall syscall) + { + _syscall = syscall; + } + + // IPC + + public KernelResult ConnectToNamedPort32([R(1)] uint namePtr, [R(1)] out int handle) + { + return _syscall.ConnectToNamedPort(namePtr, out handle); + } + + public KernelResult SendSyncRequest32([R(0)] int handle) + { + return _syscall.SendSyncRequest(handle); + } + + public KernelResult SendSyncRequestWithUserBuffer32([R(0)] uint messagePtr, [R(1)] uint size, [R(2)] int handle) + { + return _syscall.SendSyncRequestWithUserBuffer(messagePtr, size, handle); + } + + public KernelResult CreateSession32( + [R(2)] bool isLight, + [R(3)] uint namePtr, + [R(1)] out int serverSessionHandle, + [R(2)] out int clientSessionHandle) + { + return _syscall.CreateSession(isLight, namePtr, out serverSessionHandle, out clientSessionHandle); + } + + public KernelResult AcceptSession32([R(1)] int portHandle, [R(1)] out int sessionHandle) + { + return _syscall.AcceptSession(portHandle, out sessionHandle); + } + + public KernelResult ReplyAndReceive32( + [R(0)] uint timeoutLow, + [R(1)] ulong handlesPtr, + [R(2)] int handlesCount, + [R(3)] int replyTargetHandle, + [R(4)] uint timeoutHigh, + [R(1)] out int handleIndex) + { + long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32)); + + return _syscall.ReplyAndReceive(handlesPtr, handlesCount, replyTargetHandle, timeout, out handleIndex); + } + + public KernelResult CreatePort32( + [R(0)] uint namePtr, + [R(2)] int maxSessions, + [R(3)] bool isLight, + [R(1)] out int serverPortHandle, + [R(2)] out int clientPortHandle) + { + return _syscall.CreatePort(maxSessions, isLight, namePtr, out serverPortHandle, out clientPortHandle); + } + + public KernelResult ManageNamedPort32([R(1)] uint namePtr, [R(2)] int maxSessions, [R(1)] out int handle) + { + return _syscall.ManageNamedPort(namePtr, maxSessions, out handle); + } + + public KernelResult ConnectToPort32([R(1)] int clientPortHandle, [R(1)] out int clientSessionHandle) + { + return _syscall.ConnectToPort(clientPortHandle, out clientSessionHandle); + } + + // Memory + + public KernelResult SetHeapSize32([R(1)] uint size, [R(1)] out uint position) + { + KernelResult result = _syscall.SetHeapSize(size, out ulong temporaryPosition); + + position = (uint)temporaryPosition; + + return result; + } + + public KernelResult SetMemoryAttribute32( + [R(0)] uint position, + [R(1)] uint size, + [R(2)] MemoryAttribute attributeMask, + [R(3)] MemoryAttribute attributeValue) + { + return _syscall.SetMemoryAttribute(position, size, attributeMask, attributeValue); + } + + public KernelResult MapMemory32([R(0)] uint dst, [R(1)] uint src, [R(2)] uint size) + { + return _syscall.MapMemory(dst, src, size); + } + + public KernelResult UnmapMemory32([R(0)] uint dst, [R(1)] uint src, [R(2)] uint size) + { + return _syscall.UnmapMemory(dst, src, size); + } + + public KernelResult QueryMemory32([R(0)] uint infoPtr, [R(1)] uint r1, [R(2)] uint position, [R(1)] out uint pageInfo) + { + KernelResult result = _syscall.QueryMemory(infoPtr, position, out ulong pageInfo64); + + pageInfo = (uint)pageInfo64; + + return result; + } + + public KernelResult MapSharedMemory32([R(0)] int handle, [R(1)] uint address, [R(2)] uint size, [R(3)] MemoryPermission permission) + { + return _syscall.MapSharedMemory(handle, address, size, permission); + } + + public KernelResult UnmapSharedMemory32([R(0)] int handle, [R(1)] uint address, [R(2)] uint size) + { + return _syscall.UnmapSharedMemory(handle, address, size); + } + + public KernelResult CreateTransferMemory32( + [R(1)] uint address, + [R(2)] uint size, + [R(3)] MemoryPermission permission, + [R(1)] out int handle) + { + return _syscall.CreateTransferMemory(address, size, permission, out handle); + } + + public KernelResult MapPhysicalMemory32([R(0)] uint address, [R(1)] uint size) + { + return _syscall.MapPhysicalMemory(address, size); + } + + public KernelResult UnmapPhysicalMemory32([R(0)] uint address, [R(1)] uint size) + { + return _syscall.UnmapPhysicalMemory(address, size); + } + + public KernelResult MapProcessCodeMemory32([R(0)] int handle, [R(1)] uint srcLow, [R(2)] uint dstLow, [R(3)] uint dstHigh, [R(4)] uint srcHigh, [R(5)] uint sizeLow, [R(6)] uint sizeHigh) + { + ulong src = srcLow | ((ulong)srcHigh << 32); + ulong dst = dstLow | ((ulong)dstHigh << 32); + ulong size = sizeLow | ((ulong)sizeHigh << 32); + + return _syscall.MapProcessCodeMemory(handle, dst, src, size); + } + + public KernelResult UnmapProcessCodeMemory32([R(0)] int handle, [R(1)] uint srcLow, [R(2)] uint dstLow, [R(3)] uint dstHigh, [R(4)] uint srcHigh, [R(5)] uint sizeLow, [R(6)] uint sizeHigh) + { + ulong src = srcLow | ((ulong)srcHigh << 32); + ulong dst = dstLow | ((ulong)dstHigh << 32); + ulong size = sizeLow | ((ulong)sizeHigh << 32); + + return _syscall.UnmapProcessCodeMemory(handle, dst, src, size); + } + + public KernelResult SetProcessMemoryPermission32( + [R(0)] int handle, + [R(1)] uint sizeLow, + [R(2)] uint srcLow, + [R(3)] uint srcHigh, + [R(4)] uint sizeHigh, + [R(5)] MemoryPermission permission) + { + ulong src = srcLow | ((ulong)srcHigh << 32); + ulong size = sizeLow | ((ulong)sizeHigh << 32); + + return _syscall.SetProcessMemoryPermission(handle, src, size, permission); + } + + // System + + public void ExitProcess32() + { + _syscall.ExitProcess(); + } + + public KernelResult TerminateProcess32([R(0)] int handle) + { + return _syscall.TerminateProcess(handle); + } + + public KernelResult SignalEvent32([R(0)] int handle) + { + return _syscall.SignalEvent(handle); + } + + public KernelResult ClearEvent32([R(0)] int handle) + { + return _syscall.ClearEvent(handle); + } + + public KernelResult CloseHandle32([R(0)] int handle) + { + return _syscall.CloseHandle(handle); + } + + public KernelResult ResetSignal32([R(0)] int handle) + { + return _syscall.ResetSignal(handle); + } + + public void GetSystemTick32([R(0)] out uint resultLow, [R(1)] out uint resultHigh) + { + ulong result = _syscall.GetSystemTick(); + + resultLow = (uint)(result & uint.MaxValue); + resultHigh = (uint)(result >> 32); + } + + public KernelResult GetProcessId32([R(1)] int handle, [R(1)] out int pidLow, [R(2)] out int pidHigh) + { + KernelResult result = _syscall.GetProcessId(handle, out long pid); + + pidLow = (int)(pid & uint.MaxValue); + pidHigh = (int)(pid >> 32); + + return result; + } + + public void Break32([R(0)] uint reason, [R(1)] uint r1, [R(2)] uint info) + { + _syscall.Break(reason); + } + + public void OutputDebugString32([R(0)] uint strPtr, [R(1)] uint size) + { + _syscall.OutputDebugString(strPtr, size); + } + + public KernelResult GetInfo32( + [R(0)] uint subIdLow, + [R(1)] uint id, + [R(2)] int handle, + [R(3)] uint subIdHigh, + [R(1)] out uint valueLow, + [R(2)] out uint valueHigh) + { + long subId = (long)(subIdLow | ((ulong)subIdHigh << 32)); + + KernelResult result = _syscall.GetInfo(id, handle, subId, out long value); + + valueHigh = (uint)(value >> 32); + valueLow = (uint)(value & uint.MaxValue); + + return result; + } + + public KernelResult CreateEvent32([R(1)] out int wEventHandle, [R(2)] out int rEventHandle) + { + return _syscall.CreateEvent(out wEventHandle, out rEventHandle); + } + + public KernelResult GetProcessList32([R(1)] ulong address, [R(2)] int maxCount, [R(1)] out int count) + { + return _syscall.GetProcessList(address, maxCount, out count); + } + + public KernelResult GetSystemInfo32([R(1)] uint subIdLow, [R(2)] uint id, [R(3)] int handle, [R(3)] uint subIdHigh, [R(1)] out int valueLow, [R(2)] out int valueHigh) + { + long subId = (long)(subIdLow | ((ulong)subIdHigh << 32)); + + KernelResult result = _syscall.GetSystemInfo(id, handle, subId, out long value); + + valueHigh = (int)(value >> 32); + valueLow = (int)(value & uint.MaxValue); + + return result; + } + + public KernelResult FlushProcessDataCache32( + [R(0)] uint processHandle, + [R(2)] uint addressLow, + [R(3)] uint addressHigh, + [R(1)] uint sizeLow, + [R(4)] uint sizeHigh) + { + // 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 KernelResult.Success; + } + + // Thread + + public KernelResult CreateThread32( + [R(1)] uint entrypoint, + [R(2)] uint argsPtr, + [R(3)] uint stackTop, + [R(0)] int priority, + [R(4)] int cpuCore, + [R(1)] out int handle) + { + return _syscall.CreateThread(entrypoint, argsPtr, stackTop, priority, cpuCore, out handle); + } + + public KernelResult StartThread32([R(0)] int handle) + { + return _syscall.StartThread(handle); + } + + public void ExitThread32() + { + _syscall.ExitThread(); + } + + public void SleepThread32([R(0)] uint timeoutLow, [R(1)] uint timeoutHigh) + { + long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32)); + + _syscall.SleepThread(timeout); + } + + public KernelResult GetThreadPriority32([R(1)] int handle, [R(1)] out int priority) + { + return _syscall.GetThreadPriority(handle, out priority); + } + + public KernelResult SetThreadPriority32([R(0)] int handle, [R(1)] int priority) + { + return _syscall.SetThreadPriority(handle, priority); + } + + public KernelResult GetThreadCoreMask32([R(2)] int handle, [R(1)] out int preferredCore, [R(2)] out int affinityMaskLow, [R(3)] out int affinityMaskHigh) + { + KernelResult result = _syscall.GetThreadCoreMask(handle, out preferredCore, out long affinityMask); + + affinityMaskLow = (int)(affinityMask >> 32); + affinityMaskHigh = (int)(affinityMask & uint.MaxValue); + + return result; + } + + public KernelResult SetThreadCoreMask32([R(0)] int handle, [R(1)] int preferredCore, [R(2)] uint affinityMaskLow, [R(3)] uint affinityMaskHigh) + { + long affinityMask = (long)(affinityMaskLow | ((ulong)affinityMaskHigh << 32)); + + return _syscall.SetThreadCoreMask(handle, preferredCore, affinityMask); + } + + public int GetCurrentProcessorNumber32() + { + return _syscall.GetCurrentProcessorNumber(); + } + + public KernelResult GetThreadId32([R(1)] int handle, [R(1)] out uint threadUidLow, [R(2)] out uint threadUidHigh) + { + long threadUid; + + KernelResult result = _syscall.GetThreadId(handle, out threadUid); + + threadUidLow = (uint)(threadUid >> 32); + threadUidHigh = (uint)(threadUid & uint.MaxValue); + + return result; + } + + public KernelResult SetThreadActivity32([R(0)] int handle, [R(1)] bool pause) + { + return _syscall.SetThreadActivity(handle, pause); + } + + public KernelResult GetThreadContext332([R(0)] uint address, [R(1)] int handle) + { + return _syscall.GetThreadContext3(address, handle); + } + + // Thread synchronization + + public KernelResult WaitSynchronization32( + [R(0)] uint timeoutLow, + [R(1)] uint handlesPtr, + [R(2)] int handlesCount, + [R(3)] uint timeoutHigh, + [R(1)] out int handleIndex) + { + long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32)); + + return _syscall.WaitSynchronization(handlesPtr, handlesCount, timeout, out handleIndex); + } + + public KernelResult CancelSynchronization32([R(0)] int handle) + { + return _syscall.CancelSynchronization(handle); + } + + + public KernelResult ArbitrateLock32([R(0)] int ownerHandle, [R(1)] uint mutexAddress, [R(2)] int requesterHandle) + { + return _syscall.ArbitrateLock(ownerHandle, mutexAddress, requesterHandle); + } + + public KernelResult ArbitrateUnlock32([R(0)] uint mutexAddress) + { + return _syscall.ArbitrateUnlock(mutexAddress); + } + + public KernelResult WaitProcessWideKeyAtomic32( + [R(0)] uint mutexAddress, + [R(1)] uint condVarAddress, + [R(2)] int handle, + [R(3)] uint timeoutLow, + [R(4)] uint timeoutHigh) + { + long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32)); + + return _syscall.WaitProcessWideKeyAtomic(mutexAddress, condVarAddress, handle, timeout); + } + + public KernelResult SignalProcessWideKey32([R(0)] uint address, [R(1)] int count) + { + return _syscall.SignalProcessWideKey(address, count); + } + + public KernelResult WaitForAddress32([R(0)] uint address, [R(1)] ArbitrationType type, [R(2)] int value, [R(3)] uint timeoutLow, [R(4)] uint timeoutHigh) + { + long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32)); + + return _syscall.WaitForAddress(address, type, value, timeout); + } + + public KernelResult SignalToAddress32([R(0)] uint address, [R(1)] SignalType type, [R(2)] int value, [R(3)] int count) + { + return _syscall.SignalToAddress(address, type, value, count); + } + } +} diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs new file mode 100644 index 000000000..5dfcdcba9 --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs @@ -0,0 +1,338 @@ +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Memory; +using Ryujinx.HLE.HOS.Kernel.Threading; + +namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall +{ + class Syscall64 + { + private readonly Syscall _syscall; + + public Syscall64(Syscall syscall) + { + _syscall = syscall; + } + + // IPC + + public KernelResult ConnectToNamedPort64([R(1)] ulong namePtr, [R(1)] out int handle) + { + return _syscall.ConnectToNamedPort(namePtr, out handle); + } + + public KernelResult SendSyncRequest64([R(0)] int handle) + { + return _syscall.SendSyncRequest(handle); + } + + public KernelResult SendSyncRequestWithUserBuffer64([R(0)] ulong messagePtr, [R(1)] ulong size, [R(2)] int handle) + { + return _syscall.SendSyncRequestWithUserBuffer(messagePtr, size, handle); + } + + public KernelResult CreateSession64( + [R(2)] bool isLight, + [R(3)] ulong namePtr, + [R(1)] out int serverSessionHandle, + [R(2)] out int clientSessionHandle) + { + return _syscall.CreateSession(isLight, namePtr, out serverSessionHandle, out clientSessionHandle); + } + + public KernelResult AcceptSession64([R(1)] int portHandle, [R(1)] out int sessionHandle) + { + return _syscall.AcceptSession(portHandle, out sessionHandle); + } + + public KernelResult ReplyAndReceive64( + [R(1)] ulong handlesPtr, + [R(2)] int handlesCount, + [R(3)] int replyTargetHandle, + [R(4)] long timeout, + [R(1)] out int handleIndex) + { + return _syscall.ReplyAndReceive(handlesPtr, handlesCount, replyTargetHandle, timeout, out handleIndex); + } + + public KernelResult CreatePort64( + [R(2)] int maxSessions, + [R(3)] bool isLight, + [R(4)] ulong namePtr, + [R(1)] out int serverPortHandle, + [R(2)] out int clientPortHandle) + { + return _syscall.CreatePort(maxSessions, isLight, namePtr, out serverPortHandle, out clientPortHandle); + } + + public KernelResult ManageNamedPort64([R(1)] ulong namePtr, [R(2)] int maxSessions, [R(1)] out int handle) + { + return _syscall.ManageNamedPort(namePtr, maxSessions, out handle); + } + + public KernelResult ConnectToPort64([R(1)] int clientPortHandle, [R(1)] out int clientSessionHandle) + { + return _syscall.ConnectToPort(clientPortHandle, out clientSessionHandle); + } + + // Memory + + public KernelResult SetHeapSize64([R(1)] ulong size, [R(1)] out ulong position) + { + return _syscall.SetHeapSize(size, out position); + } + + public KernelResult SetMemoryAttribute64( + [R(0)] ulong position, + [R(1)] ulong size, + [R(2)] MemoryAttribute attributeMask, + [R(3)] MemoryAttribute attributeValue) + { + return _syscall.SetMemoryAttribute(position, size, attributeMask, attributeValue); + } + + public KernelResult MapMemory64([R(0)] ulong dst, [R(1)] ulong src, [R(2)] ulong size) + { + return _syscall.MapMemory(dst, src, size); + } + + public KernelResult UnmapMemory64([R(0)] ulong dst, [R(1)] ulong src, [R(2)] ulong size) + { + return _syscall.UnmapMemory(dst, src, size); + } + + public KernelResult QueryMemory64([R(0)] ulong infoPtr, [R(2)] ulong position, [R(1)] out ulong pageInfo) + { + return _syscall.QueryMemory(infoPtr, position, out pageInfo); + } + + public KernelResult MapSharedMemory64([R(0)] int handle, [R(1)] ulong address, [R(2)] ulong size, [R(3)] MemoryPermission permission) + { + return _syscall.MapSharedMemory(handle, address, size, permission); + } + + public KernelResult UnmapSharedMemory64([R(0)] int handle, [R(1)] ulong address, [R(2)] ulong size) + { + return _syscall.UnmapSharedMemory(handle, address, size); + } + + public KernelResult CreateTransferMemory64( + [R(1)] ulong address, + [R(2)] ulong size, + [R(3)] MemoryPermission permission, + [R(1)] out int handle) + { + return _syscall.CreateTransferMemory(address, size, permission, out handle); + } + + public KernelResult MapPhysicalMemory64([R(0)] ulong address, [R(1)] ulong size) + { + return _syscall.MapPhysicalMemory(address, size); + } + + public KernelResult UnmapPhysicalMemory64([R(0)] ulong address, [R(1)] ulong size) + { + return _syscall.UnmapPhysicalMemory(address, size); + } + + public KernelResult MapProcessCodeMemory64([R(0)] int handle, [R(1)] ulong dst, [R(2)] ulong src, [R(3)] ulong size) + { + return _syscall.MapProcessCodeMemory(handle, dst, src, size); + } + + public KernelResult UnmapProcessCodeMemory64([R(0)] int handle, [R(1)] ulong dst, [R(2)] ulong src, [R(3)] ulong size) + { + return _syscall.UnmapProcessCodeMemory(handle, dst, src, size); + } + + public KernelResult SetProcessMemoryPermission64([R(0)] int handle, [R(1)] ulong src, [R(2)] ulong size, [R(3)] MemoryPermission permission) + { + return _syscall.SetProcessMemoryPermission(handle, src, size, permission); + } + + // System + + public void ExitProcess64() + { + _syscall.ExitProcess(); + } + + public KernelResult TerminateProcess64([R(0)] int handle) + { + return _syscall.TerminateProcess(handle); + } + + public KernelResult SignalEvent64([R(0)] int handle) + { + return _syscall.SignalEvent(handle); + } + + public KernelResult ClearEvent64([R(0)] int handle) + { + return _syscall.ClearEvent(handle); + } + + public KernelResult CloseHandle64([R(0)] int handle) + { + return _syscall.CloseHandle(handle); + } + + public KernelResult ResetSignal64([R(0)] int handle) + { + return _syscall.ResetSignal(handle); + } + + public ulong GetSystemTick64() + { + return _syscall.GetSystemTick(); + } + + public KernelResult GetProcessId64([R(1)] int handle, [R(1)] out long pid) + { + return _syscall.GetProcessId(handle, out pid); + } + + public void Break64([R(0)] ulong reason, [R(1)] ulong x1, [R(2)] ulong info) + { + _syscall.Break(reason); + } + + public void OutputDebugString64([R(0)] ulong strPtr, [R(1)] ulong size) + { + _syscall.OutputDebugString(strPtr, size); + } + + public KernelResult GetInfo64([R(1)] uint id, [R(2)] int handle, [R(3)] long subId, [R(1)] out long value) + { + return _syscall.GetInfo(id, handle, subId, out value); + } + + public KernelResult CreateEvent64([R(1)] out int wEventHandle, [R(2)] out int rEventHandle) + { + return _syscall.CreateEvent(out wEventHandle, out rEventHandle); + } + + public KernelResult GetProcessList64([R(1)] ulong address, [R(2)] int maxCount, [R(1)] out int count) + { + return _syscall.GetProcessList(address, maxCount, out count); + } + + public KernelResult GetSystemInfo64([R(1)] uint id, [R(2)] int handle, [R(3)] long subId, [R(1)] out long value) + { + return _syscall.GetSystemInfo(id, handle, subId, out value); + } + + // Thread + + public KernelResult CreateThread64( + [R(1)] ulong entrypoint, + [R(2)] ulong argsPtr, + [R(3)] ulong stackTop, + [R(4)] int priority, + [R(5)] int cpuCore, + [R(1)] out int handle) + { + return _syscall.CreateThread(entrypoint, argsPtr, stackTop, priority, cpuCore, out handle); + } + + public KernelResult StartThread64([R(0)] int handle) + { + return _syscall.StartThread(handle); + } + + public void ExitThread64() + { + _syscall.ExitThread(); + } + + public void SleepThread64([R(0)] long timeout) + { + _syscall.SleepThread(timeout); + } + + public KernelResult GetThreadPriority64([R(1)] int handle, [R(1)] out int priority) + { + return _syscall.GetThreadPriority(handle, out priority); + } + + public KernelResult SetThreadPriority64([R(0)] int handle, [R(1)] int priority) + { + return _syscall.SetThreadPriority(handle, priority); + } + + public KernelResult GetThreadCoreMask64([R(2)] int handle, [R(1)] out int preferredCore, [R(2)] out long affinityMask) + { + return _syscall.GetThreadCoreMask(handle, out preferredCore, out affinityMask); + } + + public KernelResult SetThreadCoreMask64([R(0)] int handle, [R(1)] int preferredCore, [R(2)] long affinityMask) + { + return _syscall.SetThreadCoreMask(handle, preferredCore, affinityMask); + } + + public int GetCurrentProcessorNumber64() + { + return _syscall.GetCurrentProcessorNumber(); + } + + public KernelResult GetThreadId64([R(1)] int handle, [R(1)] out long threadUid) + { + return _syscall.GetThreadId(handle, out threadUid); + } + + public KernelResult SetThreadActivity64([R(0)] int handle, [R(1)] bool pause) + { + return _syscall.SetThreadActivity(handle, pause); + } + + public KernelResult GetThreadContext364([R(0)] ulong address, [R(1)] int handle) + { + return _syscall.GetThreadContext3(address, handle); + } + + // Thread synchronization + + public KernelResult WaitSynchronization64([R(1)] ulong handlesPtr, [R(2)] int handlesCount, [R(3)] long timeout, [R(1)] out int handleIndex) + { + return _syscall.WaitSynchronization(handlesPtr, handlesCount, timeout, out handleIndex); + } + + public KernelResult CancelSynchronization64([R(0)] int handle) + { + return _syscall.CancelSynchronization(handle); + } + + public KernelResult ArbitrateLock64([R(0)] int ownerHandle, [R(1)] ulong mutexAddress, [R(2)] int requesterHandle) + { + return _syscall.ArbitrateLock(ownerHandle, mutexAddress, requesterHandle); + } + + public KernelResult ArbitrateUnlock64([R(0)] ulong mutexAddress) + { + return _syscall.ArbitrateUnlock(mutexAddress); + } + + public KernelResult WaitProcessWideKeyAtomic64( + [R(0)] ulong mutexAddress, + [R(1)] ulong condVarAddress, + [R(2)] int handle, + [R(3)] long timeout) + { + return _syscall.WaitProcessWideKeyAtomic(mutexAddress, condVarAddress, handle, timeout); + } + + public KernelResult SignalProcessWideKey64([R(0)] ulong address, [R(1)] int count) + { + return _syscall.SignalProcessWideKey(address, count); + } + + public KernelResult WaitForAddress64([R(0)] ulong address, [R(1)] ArbitrationType type, [R(2)] int value, [R(3)] long timeout) + { + return _syscall.WaitForAddress(address, type, value, timeout); + } + + public KernelResult SignalToAddress64([R(0)] ulong address, [R(1)] SignalType type, [R(2)] int value, [R(3)] int count) + { + return _syscall.SignalToAddress(address, type, value, count); + } + } +} diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallHandler.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallHandler.cs new file mode 100644 index 000000000..2d1a3eea4 --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallHandler.cs @@ -0,0 +1,57 @@ +using ARMeilleure.State; +using Ryujinx.HLE.HOS.Kernel.Threading; +using System; + +namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall +{ + partial class SyscallHandler + { + private readonly KernelContext _context; + private readonly Syscall32 _syscall32; + private readonly Syscall64 _syscall64; + + public SyscallHandler(KernelContext context) + { + _context = context; + _syscall32 = new Syscall32(context.Syscall); + _syscall64 = new Syscall64(context.Syscall); + } + + public void SvcCall(object sender, InstExceptionEventArgs e) + { + ExecutionContext context = (ExecutionContext)sender; + + if (context.IsAarch32) + { + var svcFunc = SyscallTable.SvcTable32[e.Id]; + + if (svcFunc == null) + { + throw new NotImplementedException($"SVC 0x{e.Id:X4} is not implemented."); + } + + svcFunc(_syscall32, context); + } + else + { + var svcFunc = SyscallTable.SvcTable64[e.Id]; + + if (svcFunc == null) + { + throw new NotImplementedException($"SVC 0x{e.Id:X4} is not implemented."); + } + + svcFunc(_syscall64, context); + } + + PostSvcHandler(); + } + + private void PostSvcHandler() + { + KThread currentThread = _context.Scheduler.GetCurrentThread(); + + currentThread.HandlePostSyscall(); + } + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallTable.cs similarity index 53% rename from Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs rename to Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallTable.cs index 10abab222..043a54afb 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallTable.cs @@ -3,165 +3,164 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Kernel.Common; using System; using System.Collections.Generic; -using System.Linq; using System.Reflection; using System.Reflection.Emit; namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { - static class SvcTable + static class SyscallTable { private const int SvcFuncMaxArguments64 = 8; private const int SvcFuncMaxArguments32 = 4; private const int SvcMax = 0x80; - public static Action[] SvcTable32 { get; } - public static Action[] SvcTable64 { get; } + public static Action[] SvcTable32 { get; } + public static Action[] SvcTable64 { get; } - static SvcTable() + static SyscallTable() { - SvcTable32 = new Action[SvcMax]; - SvcTable64 = new Action[SvcMax]; + SvcTable32 = new Action[SvcMax]; + SvcTable64 = new Action[SvcMax]; Dictionary svcFuncs64 = new Dictionary { - { 0x01, nameof(SvcHandler.SetHeapSize64) }, - { 0x03, nameof(SvcHandler.SetMemoryAttribute64) }, - { 0x04, nameof(SvcHandler.MapMemory64) }, - { 0x05, nameof(SvcHandler.UnmapMemory64) }, - { 0x06, nameof(SvcHandler.QueryMemory64) }, - { 0x07, nameof(SvcHandler.ExitProcess64) }, - { 0x08, nameof(SvcHandler.CreateThread64) }, - { 0x09, nameof(SvcHandler.StartThread64) }, - { 0x0a, nameof(SvcHandler.ExitThread64) }, - { 0x0b, nameof(SvcHandler.SleepThread64) }, - { 0x0c, nameof(SvcHandler.GetThreadPriority64) }, - { 0x0d, nameof(SvcHandler.SetThreadPriority64) }, - { 0x0e, nameof(SvcHandler.GetThreadCoreMask64) }, - { 0x0f, nameof(SvcHandler.SetThreadCoreMask64) }, - { 0x10, nameof(SvcHandler.GetCurrentProcessorNumber64) }, - { 0x11, nameof(SvcHandler.SignalEvent64) }, - { 0x12, nameof(SvcHandler.ClearEvent64) }, - { 0x13, nameof(SvcHandler.MapSharedMemory64) }, - { 0x14, nameof(SvcHandler.UnmapSharedMemory64) }, - { 0x15, nameof(SvcHandler.CreateTransferMemory64) }, - { 0x16, nameof(SvcHandler.CloseHandle64) }, - { 0x17, nameof(SvcHandler.ResetSignal64) }, - { 0x18, nameof(SvcHandler.WaitSynchronization64) }, - { 0x19, nameof(SvcHandler.CancelSynchronization64) }, - { 0x1a, nameof(SvcHandler.ArbitrateLock64) }, - { 0x1b, nameof(SvcHandler.ArbitrateUnlock64) }, - { 0x1c, nameof(SvcHandler.WaitProcessWideKeyAtomic64) }, - { 0x1d, nameof(SvcHandler.SignalProcessWideKey64) }, - { 0x1e, nameof(SvcHandler.GetSystemTick64) }, - { 0x1f, nameof(SvcHandler.ConnectToNamedPort64) }, - { 0x21, nameof(SvcHandler.SendSyncRequest64) }, - { 0x22, nameof(SvcHandler.SendSyncRequestWithUserBuffer64) }, - { 0x24, nameof(SvcHandler.GetProcessId64) }, - { 0x25, nameof(SvcHandler.GetThreadId64) }, - { 0x26, nameof(SvcHandler.Break64) }, - { 0x27, nameof(SvcHandler.OutputDebugString64) }, - { 0x29, nameof(SvcHandler.GetInfo64) }, - { 0x2c, nameof(SvcHandler.MapPhysicalMemory64) }, - { 0x2d, nameof(SvcHandler.UnmapPhysicalMemory64) }, - { 0x32, nameof(SvcHandler.SetThreadActivity64) }, - { 0x33, nameof(SvcHandler.GetThreadContext364) }, - { 0x34, nameof(SvcHandler.WaitForAddress64) }, - { 0x35, nameof(SvcHandler.SignalToAddress64) }, - { 0x40, nameof(SvcHandler.CreateSession64) }, - { 0x41, nameof(SvcHandler.AcceptSession64) }, - { 0x43, nameof(SvcHandler.ReplyAndReceive64) }, - { 0x45, nameof(SvcHandler.CreateEvent64) }, - { 0x65, nameof(SvcHandler.GetProcessList64) }, - { 0x6f, nameof(SvcHandler.GetSystemInfo64) }, - { 0x70, nameof(SvcHandler.CreatePort64) }, - { 0x71, nameof(SvcHandler.ManageNamedPort64) }, - { 0x72, nameof(SvcHandler.ConnectToPort64) }, - { 0x73, nameof(SvcHandler.SetProcessMemoryPermission64) }, - { 0x77, nameof(SvcHandler.MapProcessCodeMemory64) }, - { 0x78, nameof(SvcHandler.UnmapProcessCodeMemory64) }, - { 0x7B, nameof(SvcHandler.TerminateProcess64) } + { 0x01, nameof(Syscall64.SetHeapSize64) }, + { 0x03, nameof(Syscall64.SetMemoryAttribute64) }, + { 0x04, nameof(Syscall64.MapMemory64) }, + { 0x05, nameof(Syscall64.UnmapMemory64) }, + { 0x06, nameof(Syscall64.QueryMemory64) }, + { 0x07, nameof(Syscall64.ExitProcess64) }, + { 0x08, nameof(Syscall64.CreateThread64) }, + { 0x09, nameof(Syscall64.StartThread64) }, + { 0x0a, nameof(Syscall64.ExitThread64) }, + { 0x0b, nameof(Syscall64.SleepThread64) }, + { 0x0c, nameof(Syscall64.GetThreadPriority64) }, + { 0x0d, nameof(Syscall64.SetThreadPriority64) }, + { 0x0e, nameof(Syscall64.GetThreadCoreMask64) }, + { 0x0f, nameof(Syscall64.SetThreadCoreMask64) }, + { 0x10, nameof(Syscall64.GetCurrentProcessorNumber64) }, + { 0x11, nameof(Syscall64.SignalEvent64) }, + { 0x12, nameof(Syscall64.ClearEvent64) }, + { 0x13, nameof(Syscall64.MapSharedMemory64) }, + { 0x14, nameof(Syscall64.UnmapSharedMemory64) }, + { 0x15, nameof(Syscall64.CreateTransferMemory64) }, + { 0x16, nameof(Syscall64.CloseHandle64) }, + { 0x17, nameof(Syscall64.ResetSignal64) }, + { 0x18, nameof(Syscall64.WaitSynchronization64) }, + { 0x19, nameof(Syscall64.CancelSynchronization64) }, + { 0x1a, nameof(Syscall64.ArbitrateLock64) }, + { 0x1b, nameof(Syscall64.ArbitrateUnlock64) }, + { 0x1c, nameof(Syscall64.WaitProcessWideKeyAtomic64) }, + { 0x1d, nameof(Syscall64.SignalProcessWideKey64) }, + { 0x1e, nameof(Syscall64.GetSystemTick64) }, + { 0x1f, nameof(Syscall64.ConnectToNamedPort64) }, + { 0x21, nameof(Syscall64.SendSyncRequest64) }, + { 0x22, nameof(Syscall64.SendSyncRequestWithUserBuffer64) }, + { 0x24, nameof(Syscall64.GetProcessId64) }, + { 0x25, nameof(Syscall64.GetThreadId64) }, + { 0x26, nameof(Syscall64.Break64) }, + { 0x27, nameof(Syscall64.OutputDebugString64) }, + { 0x29, nameof(Syscall64.GetInfo64) }, + { 0x2c, nameof(Syscall64.MapPhysicalMemory64) }, + { 0x2d, nameof(Syscall64.UnmapPhysicalMemory64) }, + { 0x32, nameof(Syscall64.SetThreadActivity64) }, + { 0x33, nameof(Syscall64.GetThreadContext364) }, + { 0x34, nameof(Syscall64.WaitForAddress64) }, + { 0x35, nameof(Syscall64.SignalToAddress64) }, + { 0x40, nameof(Syscall64.CreateSession64) }, + { 0x41, nameof(Syscall64.AcceptSession64) }, + { 0x43, nameof(Syscall64.ReplyAndReceive64) }, + { 0x45, nameof(Syscall64.CreateEvent64) }, + { 0x65, nameof(Syscall64.GetProcessList64) }, + { 0x6f, nameof(Syscall64.GetSystemInfo64) }, + { 0x70, nameof(Syscall64.CreatePort64) }, + { 0x71, nameof(Syscall64.ManageNamedPort64) }, + { 0x72, nameof(Syscall64.ConnectToPort64) }, + { 0x73, nameof(Syscall64.SetProcessMemoryPermission64) }, + { 0x77, nameof(Syscall64.MapProcessCodeMemory64) }, + { 0x78, nameof(Syscall64.UnmapProcessCodeMemory64) }, + { 0x7B, nameof(Syscall64.TerminateProcess64) } }; foreach (KeyValuePair value in svcFuncs64) { - SvcTable64[value.Key] = GenerateMethod(value.Value, SvcFuncMaxArguments64); + SvcTable64[value.Key] = GenerateMethod(value.Value, SvcFuncMaxArguments64); } Dictionary svcFuncs32 = new Dictionary { - { 0x01, nameof(SvcHandler.SetHeapSize32) }, - { 0x03, nameof(SvcHandler.SetMemoryAttribute32) }, - { 0x04, nameof(SvcHandler.MapMemory32) }, - { 0x05, nameof(SvcHandler.UnmapMemory32) }, - { 0x06, nameof(SvcHandler.QueryMemory32) }, - { 0x07, nameof(SvcHandler.ExitProcess32) }, - { 0x08, nameof(SvcHandler.CreateThread32) }, - { 0x09, nameof(SvcHandler.StartThread32) }, - { 0x0a, nameof(SvcHandler.ExitThread32) }, - { 0x0b, nameof(SvcHandler.SleepThread32) }, - { 0x0c, nameof(SvcHandler.GetThreadPriority32) }, - { 0x0d, nameof(SvcHandler.SetThreadPriority32) }, - { 0x0e, nameof(SvcHandler.GetThreadCoreMask32) }, - { 0x0f, nameof(SvcHandler.SetThreadCoreMask32) }, - { 0x10, nameof(SvcHandler.GetCurrentProcessorNumber32) }, - { 0x11, nameof(SvcHandler.SignalEvent32) }, - { 0x12, nameof(SvcHandler.ClearEvent32) }, - { 0x13, nameof(SvcHandler.MapSharedMemory32) }, - { 0x14, nameof(SvcHandler.UnmapSharedMemory32) }, - { 0x15, nameof(SvcHandler.CreateTransferMemory32) }, - { 0x16, nameof(SvcHandler.CloseHandle32) }, - { 0x17, nameof(SvcHandler.ResetSignal32) }, - { 0x18, nameof(SvcHandler.WaitSynchronization32) }, - { 0x19, nameof(SvcHandler.CancelSynchronization32) }, - { 0x1a, nameof(SvcHandler.ArbitrateLock32) }, - { 0x1b, nameof(SvcHandler.ArbitrateUnlock32) }, - { 0x1c, nameof(SvcHandler.WaitProcessWideKeyAtomic32) }, - { 0x1d, nameof(SvcHandler.SignalProcessWideKey32) }, - { 0x1e, nameof(SvcHandler.GetSystemTick32) }, - { 0x1f, nameof(SvcHandler.ConnectToNamedPort32) }, - { 0x21, nameof(SvcHandler.SendSyncRequest32) }, - { 0x22, nameof(SvcHandler.SendSyncRequestWithUserBuffer32) }, - { 0x24, nameof(SvcHandler.GetProcessId32) }, - { 0x25, nameof(SvcHandler.GetThreadId32) }, - { 0x26, nameof(SvcHandler.Break32) }, - { 0x27, nameof(SvcHandler.OutputDebugString32) }, - { 0x29, nameof(SvcHandler.GetInfo32) }, - { 0x2c, nameof(SvcHandler.MapPhysicalMemory32) }, - { 0x2d, nameof(SvcHandler.UnmapPhysicalMemory32) }, - { 0x32, nameof(SvcHandler.SetThreadActivity32) }, - { 0x33, nameof(SvcHandler.GetThreadContext332) }, - { 0x34, nameof(SvcHandler.WaitForAddress32) }, - { 0x35, nameof(SvcHandler.SignalToAddress32) }, - { 0x40, nameof(SvcHandler.CreateSession32) }, - { 0x41, nameof(SvcHandler.AcceptSession32) }, - { 0x43, nameof(SvcHandler.ReplyAndReceive32) }, - { 0x45, nameof(SvcHandler.CreateEvent32) }, - { 0x5F, nameof(SvcHandler.FlushProcessDataCache32) }, - { 0x65, nameof(SvcHandler.GetProcessList32) }, - { 0x6f, nameof(SvcHandler.GetSystemInfo32) }, - { 0x70, nameof(SvcHandler.CreatePort32) }, - { 0x71, nameof(SvcHandler.ManageNamedPort32) }, - { 0x72, nameof(SvcHandler.ConnectToPort32) }, - { 0x73, nameof(SvcHandler.SetProcessMemoryPermission32) }, - { 0x77, nameof(SvcHandler.MapProcessCodeMemory32) }, - { 0x78, nameof(SvcHandler.UnmapProcessCodeMemory32) }, - { 0x7B, nameof(SvcHandler.TerminateProcess32) } + { 0x01, nameof(Syscall32.SetHeapSize32) }, + { 0x03, nameof(Syscall32.SetMemoryAttribute32) }, + { 0x04, nameof(Syscall32.MapMemory32) }, + { 0x05, nameof(Syscall32.UnmapMemory32) }, + { 0x06, nameof(Syscall32.QueryMemory32) }, + { 0x07, nameof(Syscall32.ExitProcess32) }, + { 0x08, nameof(Syscall32.CreateThread32) }, + { 0x09, nameof(Syscall32.StartThread32) }, + { 0x0a, nameof(Syscall32.ExitThread32) }, + { 0x0b, nameof(Syscall32.SleepThread32) }, + { 0x0c, nameof(Syscall32.GetThreadPriority32) }, + { 0x0d, nameof(Syscall32.SetThreadPriority32) }, + { 0x0e, nameof(Syscall32.GetThreadCoreMask32) }, + { 0x0f, nameof(Syscall32.SetThreadCoreMask32) }, + { 0x10, nameof(Syscall32.GetCurrentProcessorNumber32) }, + { 0x11, nameof(Syscall32.SignalEvent32) }, + { 0x12, nameof(Syscall32.ClearEvent32) }, + { 0x13, nameof(Syscall32.MapSharedMemory32) }, + { 0x14, nameof(Syscall32.UnmapSharedMemory32) }, + { 0x15, nameof(Syscall32.CreateTransferMemory32) }, + { 0x16, nameof(Syscall32.CloseHandle32) }, + { 0x17, nameof(Syscall32.ResetSignal32) }, + { 0x18, nameof(Syscall32.WaitSynchronization32) }, + { 0x19, nameof(Syscall32.CancelSynchronization32) }, + { 0x1a, nameof(Syscall32.ArbitrateLock32) }, + { 0x1b, nameof(Syscall32.ArbitrateUnlock32) }, + { 0x1c, nameof(Syscall32.WaitProcessWideKeyAtomic32) }, + { 0x1d, nameof(Syscall32.SignalProcessWideKey32) }, + { 0x1e, nameof(Syscall32.GetSystemTick32) }, + { 0x1f, nameof(Syscall32.ConnectToNamedPort32) }, + { 0x21, nameof(Syscall32.SendSyncRequest32) }, + { 0x22, nameof(Syscall32.SendSyncRequestWithUserBuffer32) }, + { 0x24, nameof(Syscall32.GetProcessId32) }, + { 0x25, nameof(Syscall32.GetThreadId32) }, + { 0x26, nameof(Syscall32.Break32) }, + { 0x27, nameof(Syscall32.OutputDebugString32) }, + { 0x29, nameof(Syscall32.GetInfo32) }, + { 0x2c, nameof(Syscall32.MapPhysicalMemory32) }, + { 0x2d, nameof(Syscall32.UnmapPhysicalMemory32) }, + { 0x32, nameof(Syscall32.SetThreadActivity32) }, + { 0x33, nameof(Syscall32.GetThreadContext332) }, + { 0x34, nameof(Syscall32.WaitForAddress32) }, + { 0x35, nameof(Syscall32.SignalToAddress32) }, + { 0x40, nameof(Syscall32.CreateSession32) }, + { 0x41, nameof(Syscall32.AcceptSession32) }, + { 0x43, nameof(Syscall32.ReplyAndReceive32) }, + { 0x45, nameof(Syscall32.CreateEvent32) }, + { 0x5F, nameof(Syscall32.FlushProcessDataCache32) }, + { 0x65, nameof(Syscall32.GetProcessList32) }, + { 0x6f, nameof(Syscall32.GetSystemInfo32) }, + { 0x70, nameof(Syscall32.CreatePort32) }, + { 0x71, nameof(Syscall32.ManageNamedPort32) }, + { 0x72, nameof(Syscall32.ConnectToPort32) }, + { 0x73, nameof(Syscall32.SetProcessMemoryPermission32) }, + { 0x77, nameof(Syscall32.MapProcessCodeMemory32) }, + { 0x78, nameof(Syscall32.UnmapProcessCodeMemory32) }, + { 0x7B, nameof(Syscall32.TerminateProcess32) } }; foreach (KeyValuePair value in svcFuncs32) { - SvcTable32[value.Key] = GenerateMethod(value.Value, SvcFuncMaxArguments32); + SvcTable32[value.Key] = GenerateMethod(value.Value, SvcFuncMaxArguments32); } } - private static Action GenerateMethod(string svcName, int registerCleanCount) + private static Action GenerateMethod(string svcName, int registerCleanCount) { - Type[] argTypes = new Type[] { typeof(SvcHandler), typeof(ExecutionContext) }; + Type[] argTypes = new Type[] { typeof(T), typeof(ExecutionContext) }; DynamicMethod method = new DynamicMethod(svcName, null, argTypes); - MethodInfo methodInfo = typeof(SvcHandler).GetMethod(svcName); + MethodInfo methodInfo = typeof(T).GetMethod(svcName); ParameterInfo[] methodArgs = methodInfo.GetParameters(); @@ -285,7 +284,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall generator.Emit(OpCodes.Ldstr, svcName); } - MethodInfo printArgsMethod = typeof(SvcTable).GetMethod(nameof(PrintArguments), staticNonPublic); + MethodInfo printArgsMethod = typeof(SyscallTable).GetMethod(nameof(PrintArguments), staticNonPublic); generator.Emit(OpCodes.Call, printArgsMethod); @@ -343,7 +342,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall // Print result code. if (retType == typeof(KernelResult)) { - MethodInfo printResultMethod = typeof(SvcTable).GetMethod(nameof(PrintResult), staticNonPublic); + MethodInfo printResultMethod = typeof(SyscallTable).GetMethod(nameof(PrintResult), staticNonPublic); generator.Emit(OpCodes.Dup); generator.Emit(OpCodes.Ldstr, svcName); @@ -414,7 +413,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall generator.Emit(OpCodes.Ret); - return (Action)method.CreateDelegate(typeof(Action)); + return (Action)method.CreateDelegate(typeof(Action)); } private static void CheckIfTypeIsSupported(Type type, string svcName) diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs index 71ad712e7..2922ee1ac 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KAddressArbiter.cs @@ -10,40 +10,40 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { private const int HasListenersMask = 0x40000000; - private Horizon _system; + private readonly KernelContext _context; - public List CondVarThreads; - public List ArbiterThreads; + private readonly List _condVarThreads; + private readonly List _arbiterThreads; - public KAddressArbiter(Horizon system) + public KAddressArbiter(KernelContext context) { - _system = system; + _context = context; - CondVarThreads = new List(); - ArbiterThreads = new List(); + _condVarThreads = new List(); + _arbiterThreads = new List(); } public KernelResult ArbitrateLock(int ownerHandle, ulong mutexAddress, int requesterHandle) { - KThread currentThread = _system.Scheduler.GetCurrentThread(); + KThread currentThread = _context.Scheduler.GetCurrentThread(); - _system.CriticalSection.Enter(); + _context.CriticalSection.Enter(); currentThread.SignaledObj = null; currentThread.ObjSyncResult = KernelResult.Success; - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); - if (!KernelTransfer.UserToKernelInt32(_system, mutexAddress, out int mutexValue)) + if (!KernelTransfer.UserToKernelInt32(_context, mutexAddress, out int mutexValue)) { - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.InvalidMemState; } if (mutexValue != (ownerHandle | HasListenersMask)) { - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return 0; } @@ -52,7 +52,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (mutexOwner == null) { - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.InvalidHandle; } @@ -64,24 +64,24 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading currentThread.Reschedule(ThreadSchedState.Paused); - _system.CriticalSection.Leave(); - _system.CriticalSection.Enter(); + _context.CriticalSection.Leave(); + _context.CriticalSection.Enter(); if (currentThread.MutexOwner != null) { currentThread.MutexOwner.RemoveMutexWaiter(currentThread); } - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); - return (KernelResult)currentThread.ObjSyncResult; + return currentThread.ObjSyncResult; } public KernelResult ArbitrateUnlock(ulong mutexAddress) { - _system.CriticalSection.Enter(); + _context.CriticalSection.Enter(); - KThread currentThread = _system.Scheduler.GetCurrentThread(); + KThread currentThread = _context.Scheduler.GetCurrentThread(); (KernelResult result, KThread newOwnerThread) = MutexUnlock(currentThread, mutexAddress); @@ -91,7 +91,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading newOwnerThread.ObjSyncResult = result; } - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return result; } @@ -102,9 +102,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading int threadHandle, long timeout) { - _system.CriticalSection.Enter(); + _context.CriticalSection.Enter(); - KThread currentThread = _system.Scheduler.GetCurrentThread(); + KThread currentThread = _context.Scheduler.GetCurrentThread(); currentThread.SignaledObj = null; currentThread.ObjSyncResult = KernelResult.TimedOut; @@ -112,7 +112,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (currentThread.ShallBeTerminated || currentThread.SchedFlags == ThreadSchedState.TerminationPending) { - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.ThreadTerminating; } @@ -121,7 +121,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (result != KernelResult.Success) { - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return result; } @@ -130,7 +130,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading currentThread.ThreadHandleForUserMutex = threadHandle; currentThread.CondVarAddress = condVarAddress; - CondVarThreads.Add(currentThread); + _condVarThreads.Add(currentThread); if (timeout != 0) { @@ -138,29 +138,29 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (timeout > 0) { - _system.TimeManager.ScheduleFutureInvocation(currentThread, timeout); + _context.TimeManager.ScheduleFutureInvocation(currentThread, timeout); } } - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); if (timeout > 0) { - _system.TimeManager.UnscheduleFutureInvocation(currentThread); + _context.TimeManager.UnscheduleFutureInvocation(currentThread); } - _system.CriticalSection.Enter(); + _context.CriticalSection.Enter(); if (currentThread.MutexOwner != null) { currentThread.MutexOwner.RemoveMutexWaiter(currentThread); } - CondVarThreads.Remove(currentThread); + _condVarThreads.Remove(currentThread); - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); - return (KernelResult)currentThread.ObjSyncResult; + return currentThread.ObjSyncResult; } private (KernelResult, KThread) MutexUnlock(KThread currentThread, ulong mutexAddress) @@ -186,7 +186,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading KernelResult result = KernelResult.Success; - if (!KernelTransfer.KernelToUserInt32(_system, mutexAddress, mutexValue)) + if (!KernelTransfer.KernelToUserInt32(_context, mutexAddress, mutexValue)) { result = KernelResult.InvalidMemState; } @@ -198,9 +198,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { Queue signaledThreads = new Queue(); - _system.CriticalSection.Enter(); + _context.CriticalSection.Enter(); - IOrderedEnumerable sortedThreads = CondVarThreads.OrderBy(x => x.DynamicPriority); + IOrderedEnumerable sortedThreads = _condVarThreads.OrderBy(x => x.DynamicPriority); foreach (KThread thread in sortedThreads.Where(x => x.CondVarAddress == address)) { @@ -217,17 +217,17 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading while (signaledThreads.TryDequeue(out KThread thread)) { - CondVarThreads.Remove(thread); + _condVarThreads.Remove(thread); } - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); } private KThread TryAcquireMutex(KThread requester) { ulong address = requester.MutexAddress; - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); if (!currentProcess.CpuMemory.IsMapped(address)) { @@ -293,14 +293,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public KernelResult WaitForAddressIfEqual(ulong address, int value, long timeout) { - KThread currentThread = _system.Scheduler.GetCurrentThread(); + KThread currentThread = _context.Scheduler.GetCurrentThread(); - _system.CriticalSection.Enter(); + _context.CriticalSection.Enter(); if (currentThread.ShallBeTerminated || currentThread.SchedFlags == ThreadSchedState.TerminationPending) { - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.ThreadTerminating; } @@ -308,9 +308,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading currentThread.SignaledObj = null; currentThread.ObjSyncResult = KernelResult.TimedOut; - if (!KernelTransfer.UserToKernelInt32(_system, address, out int currentValue)) + if (!KernelTransfer.UserToKernelInt32(_context, address, out int currentValue)) { - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.InvalidMemState; } @@ -319,7 +319,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { if (timeout == 0) { - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.TimedOut; } @@ -327,37 +327,37 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading currentThread.MutexAddress = address; currentThread.WaitingInArbitration = true; - InsertSortedByPriority(ArbiterThreads, currentThread); + InsertSortedByPriority(_arbiterThreads, currentThread); currentThread.Reschedule(ThreadSchedState.Paused); if (timeout > 0) { - _system.TimeManager.ScheduleFutureInvocation(currentThread, timeout); + _context.TimeManager.ScheduleFutureInvocation(currentThread, timeout); } - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); if (timeout > 0) { - _system.TimeManager.UnscheduleFutureInvocation(currentThread); + _context.TimeManager.UnscheduleFutureInvocation(currentThread); } - _system.CriticalSection.Enter(); + _context.CriticalSection.Enter(); if (currentThread.WaitingInArbitration) { - ArbiterThreads.Remove(currentThread); + _arbiterThreads.Remove(currentThread); currentThread.WaitingInArbitration = false; } - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); - return (KernelResult)currentThread.ObjSyncResult; + return currentThread.ObjSyncResult; } - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.InvalidState; } @@ -368,14 +368,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading bool shouldDecrement, long timeout) { - KThread currentThread = _system.Scheduler.GetCurrentThread(); + KThread currentThread = _context.Scheduler.GetCurrentThread(); - _system.CriticalSection.Enter(); + _context.CriticalSection.Enter(); if (currentThread.ShallBeTerminated || currentThread.SchedFlags == ThreadSchedState.TerminationPending) { - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.ThreadTerminating; } @@ -383,11 +383,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading currentThread.SignaledObj = null; currentThread.ObjSyncResult = KernelResult.TimedOut; - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); - if (!KernelTransfer.UserToKernelInt32(_system, address, out int currentValue)) + if (!KernelTransfer.UserToKernelInt32(_context, address, out int currentValue)) { - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.InvalidMemState; } @@ -401,7 +401,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { if (timeout == 0) { - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.TimedOut; } @@ -409,37 +409,37 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading currentThread.MutexAddress = address; currentThread.WaitingInArbitration = true; - InsertSortedByPriority(ArbiterThreads, currentThread); + InsertSortedByPriority(_arbiterThreads, currentThread); currentThread.Reschedule(ThreadSchedState.Paused); if (timeout > 0) { - _system.TimeManager.ScheduleFutureInvocation(currentThread, timeout); + _context.TimeManager.ScheduleFutureInvocation(currentThread, timeout); } - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); if (timeout > 0) { - _system.TimeManager.UnscheduleFutureInvocation(currentThread); + _context.TimeManager.UnscheduleFutureInvocation(currentThread); } - _system.CriticalSection.Enter(); + _context.CriticalSection.Enter(); if (currentThread.WaitingInArbitration) { - ArbiterThreads.Remove(currentThread); + _arbiterThreads.Remove(currentThread); currentThread.WaitingInArbitration = false; } - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); - return (KernelResult)currentThread.ObjSyncResult; + return currentThread.ObjSyncResult; } - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.InvalidState; } @@ -470,24 +470,24 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public KernelResult Signal(ulong address, int count) { - _system.CriticalSection.Enter(); + _context.CriticalSection.Enter(); WakeArbiterThreads(address, count); - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.Success; } public KernelResult SignalAndIncrementIfEqual(ulong address, int value, int count) { - _system.CriticalSection.Enter(); + _context.CriticalSection.Enter(); - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); if (!currentProcess.CpuMemory.IsMapped(address)) { - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.InvalidMemState; } @@ -502,7 +502,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (currentValue != value) { - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.InvalidState; } @@ -511,14 +511,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading WakeArbiterThreads(address, count); - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.Success; } public KernelResult SignalAndModifyIfEqual(ulong address, int value, int count) { - _system.CriticalSection.Enter(); + _context.CriticalSection.Enter(); int offset; @@ -527,7 +527,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading // or negative. It is incremented if there are no threads waiting. int waitingCount = 0; - foreach (KThread thread in ArbiterThreads.Where(x => x.MutexAddress == address)) + foreach (KThread thread in _arbiterThreads.Where(x => x.MutexAddress == address)) { if (++waitingCount > count) { @@ -544,11 +544,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading offset = 1; } - KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); + KProcess currentProcess = _context.Scheduler.GetCurrentProcess(); if (!currentProcess.CpuMemory.IsMapped(address)) { - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.InvalidMemState; } @@ -563,7 +563,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (currentValue != value) { - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.InvalidState; } @@ -572,7 +572,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading WakeArbiterThreads(address, count); - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.Success; } @@ -581,7 +581,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { Queue signaledThreads = new Queue(); - foreach (KThread thread in ArbiterThreads.Where(x => x.MutexAddress == address)) + foreach (KThread thread in _arbiterThreads.Where(x => x.MutexAddress == address)) { signaledThreads.Enqueue(thread); @@ -601,7 +601,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading thread.WaitingInArbitration = false; - ArbiterThreads.Remove(thread); + _arbiterThreads.Remove(thread); } } } diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KConditionVariable.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KConditionVariable.cs index 414736438..dd7e67ae9 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KConditionVariable.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KConditionVariable.cs @@ -5,11 +5,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { static class KConditionVariable { - public static void Wait(Horizon system, LinkedList threadList, object mutex, long timeout) + public static void Wait(KernelContext context, LinkedList threadList, object mutex, long timeout) { - KThread currentThread = system.Scheduler.GetCurrentThread(); + KThread currentThread = context.Scheduler.GetCurrentThread(); - system.CriticalSection.Enter(); + context.CriticalSection.Enter(); Monitor.Exit(mutex); @@ -28,29 +28,29 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading currentThread.Withholder = null; - system.CriticalSection.Leave(); + context.CriticalSection.Leave(); } else { if (timeout > 0) { - system.TimeManager.ScheduleFutureInvocation(currentThread, timeout); + context.TimeManager.ScheduleFutureInvocation(currentThread, timeout); } - system.CriticalSection.Leave(); + context.CriticalSection.Leave(); if (timeout > 0) { - system.TimeManager.UnscheduleFutureInvocation(currentThread); + context.TimeManager.UnscheduleFutureInvocation(currentThread); } } Monitor.Enter(mutex); } - public static void NotifyAll(Horizon system, LinkedList threadList) + public static void NotifyAll(KernelContext context, LinkedList threadList) { - system.CriticalSection.Enter(); + context.CriticalSection.Enter(); LinkedListNode node = threadList.First; @@ -65,7 +65,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading thread.Reschedule(ThreadSchedState.Running); } - system.CriticalSection.Leave(); + context.CriticalSection.Leave(); } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs index b7013bb7b..b778c2a42 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KCriticalSection.cs @@ -1,19 +1,18 @@ -using ARMeilleure; using System.Threading; namespace Ryujinx.HLE.HOS.Kernel.Threading { class KCriticalSection { - private Horizon _system; + private readonly KernelContext _context; public object LockObj { get; private set; } private int _recursionCount; - public KCriticalSection(Horizon system) + public KCriticalSection(KernelContext context) { - _system = system; + _context = context; LockObj = new object(); } @@ -36,20 +35,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (--_recursionCount == 0) { - if (_system.Scheduler.ThreadReselectionRequested) + if (_context.Scheduler.ThreadReselectionRequested) { - _system.Scheduler.SelectThreads(); + _context.Scheduler.SelectThreads(); } Monitor.Exit(LockObj); - if (_system.Scheduler.MultiCoreScheduling) + if (_context.Scheduler.MultiCoreScheduling) { - lock (_system.Scheduler.CoreContexts) + lock (_context.Scheduler.CoreContexts) { for (int core = 0; core < KScheduler.CpuCoresCount; core++) { - KCoreContext coreContext = _system.Scheduler.CoreContexts[core]; + KCoreContext coreContext = _context.Scheduler.CoreContexts[core]; if (coreContext.ContextSwitchNeeded) { @@ -86,7 +85,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (doContextSwitch) { - _system.Scheduler.ContextSwitch(); + _context.Scheduler.ContextSwitch(); } } } diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KEvent.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KEvent.cs index dd9822918..da3e217bf 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KEvent.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KEvent.cs @@ -5,10 +5,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public KReadableEvent ReadableEvent { get; private set; } public KWritableEvent WritableEvent { get; private set; } - public KEvent(Horizon system) + public KEvent(KernelContext context) { - ReadableEvent = new KReadableEvent(system, this); - WritableEvent = new KWritableEvent(system, this); + ReadableEvent = new KReadableEvent(context, this); + WritableEvent = new KWritableEvent(context, this); } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KReadableEvent.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KReadableEvent.cs index 9821de35b..d378b81e3 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KReadableEvent.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KReadableEvent.cs @@ -4,18 +4,18 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { class KReadableEvent : KSynchronizationObject { - private KEvent _parent; + private readonly KEvent _parent; private bool _signaled; - public KReadableEvent(Horizon system, KEvent parent) : base(system) + public KReadableEvent(KernelContext context, KEvent parent) : base(context) { _parent = parent; } public override void Signal() { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if (!_signaled) { @@ -24,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading base.Signal(); } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); } public KernelResult Clear() @@ -38,7 +38,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { KernelResult result; - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if (_signaled) { @@ -51,7 +51,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading result = KernelResult.InvalidState; } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return result; } diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs index dd5422b8e..e07477ae1 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs @@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading private const int PreemptionPriorityCores012 = 59; private const int PreemptionPriorityCore3 = 63; - private Horizon _system; + private readonly KernelContext _context; public KSchedulingData SchedulingData { get; private set; } @@ -21,9 +21,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public bool ThreadReselectionRequested { get; set; } - public KScheduler(Horizon system) + public KScheduler(KernelContext context) { - _system = system; + _context = context; SchedulingData = new KSchedulingData(); @@ -39,14 +39,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading private void PreemptThreads() { - _system.CriticalSection.Enter(); + _context.CriticalSection.Enter(); PreemptThread(PreemptionPriorityCores012, 0); PreemptThread(PreemptionPriorityCores012, 1); PreemptThread(PreemptionPriorityCores012, 2); PreemptThread(PreemptionPriorityCore3, 3); - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); } private void PreemptThread(int prio, int core) @@ -224,9 +224,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading return _dummyThread; } - KProcess dummyProcess = new KProcess(_system); + KProcess dummyProcess = new KProcess(_context); - KThread dummyThread = new KThread(_system); + KThread dummyThread = new KThread(_context); dummyThread.Initialize(0, 0, 0, 44, 0, dummyProcess, ThreadType.Dummy); diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs index 865551a2d..fa9b669ea 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs @@ -5,11 +5,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { class KSynchronization { - private Horizon _system; + private KernelContext _context; - public KSynchronization(Horizon system) + public KSynchronization(KernelContext context) { - _system = system; + _context = context; } public KernelResult WaitFor(KSynchronizationObject[] syncObjs, long timeout, out int handleIndex) @@ -18,7 +18,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading KernelResult result = KernelResult.TimedOut; - _system.CriticalSection.Enter(); + _context.CriticalSection.Enter(); // Check if objects are already signaled before waiting. for (int index = 0; index < syncObjs.Length; index++) @@ -30,19 +30,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading handleIndex = index; - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return KernelResult.Success; } if (timeout == 0) { - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return result; } - KThread currentThread = _system.Scheduler.GetCurrentThread(); + KThread currentThread = _context.Scheduler.GetCurrentThread(); if (currentThread.ShallBeTerminated || currentThread.SchedFlags == ThreadSchedState.TerminationPending) @@ -72,19 +72,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (timeout > 0) { - _system.TimeManager.ScheduleFutureInvocation(currentThread, timeout); + _context.TimeManager.ScheduleFutureInvocation(currentThread, timeout); } - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); currentThread.WaitingSync = false; if (timeout > 0) { - _system.TimeManager.UnscheduleFutureInvocation(currentThread); + _context.TimeManager.UnscheduleFutureInvocation(currentThread); } - _system.CriticalSection.Enter(); + _context.CriticalSection.Enter(); result = currentThread.ObjSyncResult; @@ -101,14 +101,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading } } - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); return result; } public void SignalObject(KSynchronizationObject syncObj) { - _system.CriticalSection.Enter(); + _context.CriticalSection.Enter(); if (syncObj.IsSignaled()) { @@ -130,7 +130,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading } } - _system.CriticalSection.Leave(); + _context.CriticalSection.Leave(); } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs index 24c4b2a30..754a1e530 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs @@ -91,10 +91,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public long LastPc { get; set; } - public KThread(Horizon system) : base(system) + public KThread(KernelContext context) : base(context) { - _scheduler = system.Scheduler; - _schedulingData = system.Scheduler.SchedulingData; + _scheduler = KernelContext.Scheduler; + _schedulingData = KernelContext.Scheduler.SchedulingData; SiblingsPerCore = new LinkedListNode[KScheduler.CpuCoresCount]; @@ -185,7 +185,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading owner.SubscribeThreadEventHandlers(Context); - ThreadUid = System.GetThreadUid(); + ThreadUid = KernelContext.NewThreadUid(); HostThread.Name = $"HLE.HostThread.{ThreadUid}"; @@ -197,11 +197,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (owner.IsPaused) { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if (ShallBeTerminated || SchedFlags == ThreadSchedState.TerminationPending) { - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return KernelResult.Success; } @@ -210,7 +210,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading CombineForcePauseFlags(); - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); } } @@ -219,9 +219,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public KernelResult Start() { - if (!System.KernelInitialized) + if (!KernelContext.KernelInitialized) { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if (!ShallBeTerminated && SchedFlags != ThreadSchedState.TerminationPending) { @@ -230,16 +230,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading CombineForcePauseFlags(); } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); } KernelResult result = KernelResult.ThreadTerminating; - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if (!ShallBeTerminated) { - KThread currentThread = System.Scheduler.GetCurrentThread(); + KThread currentThread = KernelContext.Scheduler.GetCurrentThread(); while (SchedFlags != ThreadSchedState.TerminationPending && currentThread.SchedFlags != ThreadSchedState.TerminationPending && @@ -269,8 +269,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { currentThread.CombineForcePauseFlags(); - System.CriticalSection.Leave(); - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Leave(); + KernelContext.CriticalSection.Enter(); if (currentThread.ShallBeTerminated) { @@ -280,7 +280,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading } } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return result; } @@ -296,20 +296,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading _hasBeenReleased = true; } - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); _forcePauseFlags &= ~ThreadSchedState.ForcePauseMask; ExitImpl(); - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); DecrementReferenceCount(); } public ThreadSchedState PrepareForTermination() { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); ThreadSchedState result; @@ -351,7 +351,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading result = SchedFlags; - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return result & ThreadSchedState.LowMask; } @@ -362,7 +362,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (state != ThreadSchedState.TerminationPending) { - System.Synchronization.WaitFor(new KSynchronizationObject[] { this }, -1, out _); + KernelContext.Synchronization.WaitFor(new KSynchronizationObject[] { this }, -1, out _); } } @@ -374,14 +374,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { if (ShallBeTerminated || SchedFlags == ThreadSchedState.TerminationPending) { - System.Scheduler.ExitThread(this); + KernelContext.Scheduler.ExitThread(this); Exit(); // As the death of the thread is handled by the CPU emulator, we differ from the official kernel and return here. break; } - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if (ShallBeTerminated || SchedFlags == ThreadSchedState.TerminationPending) { @@ -397,13 +397,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading state = ThreadSchedState.Running; } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); } while (state == ThreadSchedState.TerminationPending); } private void ExitImpl() { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); SetNewSchedFlags(ThreadSchedState.TerminationPending); @@ -411,16 +411,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading Signal(); - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); } public KernelResult Sleep(long timeout) { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if (ShallBeTerminated || SchedFlags == ThreadSchedState.TerminationPending) { - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return KernelResult.ThreadTerminating; } @@ -429,14 +429,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if (timeout > 0) { - System.TimeManager.ScheduleFutureInvocation(this, timeout); + KernelContext.TimeManager.ScheduleFutureInvocation(this, timeout); } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); if (timeout > 0) { - System.TimeManager.UnscheduleFutureInvocation(this); + KernelContext.TimeManager.UnscheduleFutureInvocation(this); } return 0; @@ -444,13 +444,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading public void Yield() { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if (SchedFlags != ThreadSchedState.Running) { - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); - System.Scheduler.ContextSwitch(); + KernelContext.Scheduler.ContextSwitch(); return; } @@ -463,20 +463,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading _scheduler.ThreadReselectionRequested = true; - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); - System.Scheduler.ContextSwitch(); + KernelContext.Scheduler.ContextSwitch(); } public void YieldWithLoadBalancing() { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if (SchedFlags != ThreadSchedState.Running) { - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); - System.Scheduler.ContextSwitch(); + KernelContext.Scheduler.ContextSwitch(); return; } @@ -536,20 +536,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading _scheduler.ThreadReselectionRequested = true; } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); - System.Scheduler.ContextSwitch(); + KernelContext.Scheduler.ContextSwitch(); } public void YieldAndWaitForLoadBalancing() { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if (SchedFlags != ThreadSchedState.Running) { - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); - System.Scheduler.ContextSwitch(); + KernelContext.Scheduler.ContextSwitch(); return; } @@ -592,38 +592,38 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading _scheduler.ThreadReselectionRequested = true; } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); - System.Scheduler.ContextSwitch(); + KernelContext.Scheduler.ContextSwitch(); } public void SetPriority(int priority) { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); BasePriority = priority; UpdatePriorityInheritance(); - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); } public KernelResult SetActivity(bool pause) { KernelResult result = KernelResult.Success; - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); ThreadSchedState lowNibble = SchedFlags & ThreadSchedState.LowMask; if (lowNibble != ThreadSchedState.Paused && lowNibble != ThreadSchedState.Running) { - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return KernelResult.InvalidState; } - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if (!ShallBeTerminated && SchedFlags != ThreadSchedState.TerminationPending) { @@ -666,15 +666,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading } } - System.CriticalSection.Leave(); - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return result; } public void CancelSynchronization() { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if ((SchedFlags & ThreadSchedState.LowMask) != ThreadSchedState.Paused || !WaitingSync) { @@ -700,12 +700,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading SyncCancelled = false; } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); } public KernelResult SetCoreAndAffinityMask(int newCore, long newAffinityMask) { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); bool useOverride = _affinityOverrideCount != 0; @@ -716,7 +716,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading if ((newAffinityMask & (1 << newCore)) == 0) { - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return KernelResult.InvalidCombination; } @@ -754,7 +754,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading } } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); return KernelResult.Success; } @@ -784,7 +784,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading private void SetNewSchedFlags(ThreadSchedState newFlags) { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); ThreadSchedState oldFlags = SchedFlags; @@ -795,12 +795,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading AdjustScheduling(oldFlags); } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); } public void ReleaseAndResume() { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); if ((SchedFlags & ThreadSchedState.LowMask) == ThreadSchedState.Paused) { @@ -818,12 +818,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading } } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); } public void Reschedule(ThreadSchedState newFlags) { - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); ThreadSchedState oldFlags = SchedFlags; @@ -832,7 +832,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading AdjustScheduling(oldFlags); - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); } public void AddMutexWaiter(KThread requester) @@ -1150,8 +1150,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading private void ThreadExit() { - System.Scheduler.ExitThread(this); - System.Scheduler.RemoveThread(this); + KernelContext.Scheduler.ExitThread(this); + KernelContext.Scheduler.RemoveThread(this); } public bool IsCurrentHostThread() @@ -1180,7 +1180,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading } else { - System.ResourceLimit.Release(LimitableResource.Thread, 1, released ? 0 : 1); + KernelContext.ResourceLimit.Release(LimitableResource.Thread, 1, released ? 0 : 1); } } } @@ -1194,7 +1194,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading throw new InvalidOperationException("Unexpected failure freeing thread local storage."); } - System.CriticalSection.Enter(); + KernelContext.CriticalSection.Enter(); // Wake up all threads that may be waiting for a mutex being held by this thread. foreach (KThread thread in _mutexWaiters) @@ -1206,7 +1206,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading thread.ReleaseAndResume(); } - System.CriticalSection.Leave(); + KernelContext.CriticalSection.Leave(); Owner?.DecrementThreadCountAndTerminateIfZero(); } diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs index 1db88995d..7aee0b57c 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KWritableEvent.cs @@ -4,9 +4,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading { class KWritableEvent : KAutoObject { - private KEvent _parent; + private readonly KEvent _parent; - public KWritableEvent(Horizon system, KEvent parent) : base(system) + public KWritableEvent(KernelContext context, KEvent parent) : base(context) { _parent = parent; } diff --git a/Ryujinx.HLE/HOS/ProgramLoader.cs b/Ryujinx.HLE/HOS/ProgramLoader.cs index 3dd7d703f..c1e18491d 100644 --- a/Ryujinx.HLE/HOS/ProgramLoader.cs +++ b/Ryujinx.HLE/HOS/ProgramLoader.cs @@ -1,6 +1,7 @@ using Ryujinx.Common; using Ryujinx.Common.Logging; using Ryujinx.Cpu; +using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Kernel.Process; @@ -17,7 +18,7 @@ namespace Ryujinx.HLE.HOS private const int ArgsDataSize = 0x9000; private const int ArgsTotalSize = ArgsHeaderSize + ArgsDataSize; - public static bool LoadKernelInitalProcess(Horizon system, KipExecutable kip) + public static bool LoadKip(KernelContext context, KipExecutable kip) { int endOffset = kip.DataOffset + kip.Data.Length; @@ -67,7 +68,7 @@ namespace Ryujinx.HLE.HOS ? MemoryRegion.Service : MemoryRegion.Application; - KMemoryRegionManager region = system.MemoryRegions[(int)memoryRegion]; + KMemoryRegionManager region = context.MemoryRegions[(int)memoryRegion]; KernelResult result = region.AllocatePages((ulong)codePagesCount, false, out KPageList pageList); @@ -78,13 +79,13 @@ namespace Ryujinx.HLE.HOS return false; } - KProcess process = new KProcess(system); + KProcess process = new KProcess(context); result = process.InitializeKip( creationInfo, kip.Capabilities, pageList, - system.ResourceLimit, + context.ResourceLimit, memoryRegion); if (result != KernelResult.Success) @@ -114,15 +115,15 @@ namespace Ryujinx.HLE.HOS return false; } - system.Processes.Add(process.Pid, process); + context.Processes.TryAdd(process.Pid, process); return true; } - public static bool LoadStaticObjects( - Horizon system, + public static bool LoadNsos( + KernelContext context, Npdm metaData, - IExecutable[] staticObjects, + IExecutable[] nsos, byte[] arguments = null) { ulong argsStart = 0; @@ -130,11 +131,11 @@ namespace Ryujinx.HLE.HOS ulong codeStart = metaData.Is64Bit ? 0x8000000UL : 0x200000UL; int codeSize = 0; - ulong[] nsoBase = new ulong[staticObjects.Length]; + ulong[] nsoBase = new ulong[nsos.Length]; - for (int index = 0; index < staticObjects.Length; index++) + for (int index = 0; index < nsos.Length; index++) { - IExecutable staticObject = staticObjects[index]; + IExecutable staticObject = nsos[index]; int textEnd = staticObject.TextOffset + staticObject.Text.Length; int roEnd = staticObject.RoOffset + staticObject.Ro.Length; @@ -184,9 +185,9 @@ namespace Ryujinx.HLE.HOS KernelResult result; - KResourceLimit resourceLimit = new KResourceLimit(system); + KResourceLimit resourceLimit = new KResourceLimit(context); - long applicationRgSize = (long)system.MemoryRegions[(int)MemoryRegion.Application].Size; + long applicationRgSize = (long)context.MemoryRegions[(int)MemoryRegion.Application].Size; result = resourceLimit.SetLimitValue(LimitableResource.Memory, applicationRgSize); result |= resourceLimit.SetLimitValue(LimitableResource.Thread, 608); @@ -201,7 +202,7 @@ namespace Ryujinx.HLE.HOS return false; } - KProcess process = new KProcess(system); + KProcess process = new KProcess(context); MemoryRegion memoryRegion = (MemoryRegion)((metaData.Acid.Flags >> 2) & 0xf); @@ -225,11 +226,11 @@ namespace Ryujinx.HLE.HOS return false; } - for (int index = 0; index < staticObjects.Length; index++) + for (int index = 0; index < nsos.Length; index++) { Logger.PrintInfo(LogClass.Loader, $"Loading image {index} at 0x{nsoBase[index]:x16}..."); - result = LoadIntoMemory(process, staticObjects[index], nsoBase[index]); + result = LoadIntoMemory(process, nsos[index], nsoBase[index]); if (result != KernelResult.Success) { @@ -250,7 +251,7 @@ namespace Ryujinx.HLE.HOS return false; } - system.Processes.Add(process.Pid, process); + context.Processes.TryAdd(process.Pid, process); return true; } diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs index 9ebb0b99b..aedec5501 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs @@ -20,9 +20,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib public ILibraryAppletAccessor(AppletId appletId, Horizon system) { - _stateChangedEvent = new KEvent(system); - _normalOutDataEvent = new KEvent(system); - _interactiveOutDataEvent = new KEvent(system); + _stateChangedEvent = new KEvent(system.KernelContext); + _normalOutDataEvent = new KEvent(system.KernelContext); + _interactiveOutDataEvent = new KEvent(system.KernelContext); _applet = AppletManager.Create(appletId, system); diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs index a5819132d..c461c1c45 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs @@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys public IHomeMenuFunctions(Horizon system) { // TODO: Signal this Event somewhere in future. - _channelEvent = new KEvent(system); + _channelEvent = new KEvent(system.KernelContext); } [Command(10)] diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs index d7abfdfeb..b34ecefbf 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs @@ -23,7 +23,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys public ISelfController(Horizon system) { - _libraryAppletLaunchableEvent = new KEvent(system); + _libraryAppletLaunchableEvent = new KEvent(system.KernelContext); } [Command(0)] @@ -230,7 +230,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys { if (_accumulatedSuspendedTickChangedEventHandle == 0) { - _accumulatedSuspendedTickChangedEvent = new KEvent(context.Device.System); + _accumulatedSuspendedTickChangedEvent = new KEvent(context.Device.System.KernelContext); _accumulatedSuspendedTickChangedEvent.ReadableEvent.Signal(); diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs b/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs index 5d92b433a..6ba506a17 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs @@ -25,7 +25,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati public IApplicationFunctions(Horizon system) { - _gpuErrorDetectedSystemEvent = new KEvent(system); + _gpuErrorDetectedSystemEvent = new KEvent(system.KernelContext); } [Command(1)] diff --git a/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager/IAudioDevice.cs b/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager/IAudioDevice.cs index 89c064e3b..56ece87f4 100644 --- a/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager/IAudioDevice.cs +++ b/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager/IAudioDevice.cs @@ -14,7 +14,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRendererManager public IAudioDevice(Horizon system) { - _systemEvent = new KEvent(system); + _systemEvent = new KEvent(system.KernelContext); // TODO: We shouldn't be signaling this here. _systemEvent.ReadableEvent.Signal(); diff --git a/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager/IAudioRenderer.cs b/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager/IAudioRenderer.cs index e899f9450..16c06b517 100644 --- a/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager/IAudioRenderer.cs +++ b/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager/IAudioRenderer.cs @@ -48,7 +48,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRendererManager IAalOutput audioOut, AudioRendererParameter rendererParams) { - _updateEvent = new KEvent(system); + _updateEvent = new KEvent(system.KernelContext); _memory = memory; _audioOut = audioOut; diff --git a/Ryujinx.HLE/HOS/Services/Audio/IAudioOutManager.cs b/Ryujinx.HLE/HOS/Services/Audio/IAudioOutManager.cs index 370b2302c..508bed40d 100644 --- a/Ryujinx.HLE/HOS/Services/Audio/IAudioOutManager.cs +++ b/Ryujinx.HLE/HOS/Services/Audio/IAudioOutManager.cs @@ -138,7 +138,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio channels = DefaultChannelsCount; } - KEvent releaseEvent = new KEvent(context.Device.System); + KEvent releaseEvent = new KEvent(context.Device.System.KernelContext); ReleaseCallback callback = () => { diff --git a/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs b/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs index 9ffe9e997..3ee4ee68f 100644 --- a/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs +++ b/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs @@ -15,7 +15,7 @@ namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator public IDeliveryCacheProgressService(ServiceCtx context) { - _event = new KEvent(context.Device.System); + _event = new KEvent(context.Device.System.KernelContext); } [Command(0)] diff --git a/Ryujinx.HLE/HOS/Services/Bluetooth/IBluetoothDriver.cs b/Ryujinx.HLE/HOS/Services/Bluetooth/IBluetoothDriver.cs index 8b9a8a94c..8bbf26b26 100644 --- a/Ryujinx.HLE/HOS/Services/Bluetooth/IBluetoothDriver.cs +++ b/Ryujinx.HLE/HOS/Services/Bluetooth/IBluetoothDriver.cs @@ -25,7 +25,7 @@ namespace Ryujinx.HLE.HOS.Services.Bluetooth { if (BluetoothEventManager.InitializeBleDebugEventHandle == 0) { - BluetoothEventManager.InitializeBleDebugEvent = new KEvent(context.Device.System); + BluetoothEventManager.InitializeBleDebugEvent = new KEvent(context.Device.System.KernelContext); if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.InitializeBleDebugEvent.ReadableEvent, out BluetoothEventManager.InitializeBleDebugEventHandle) != KernelResult.Success) { @@ -35,7 +35,7 @@ namespace Ryujinx.HLE.HOS.Services.Bluetooth if (BluetoothEventManager.UnknownBleDebugEventHandle == 0) { - BluetoothEventManager.UnknownBleDebugEvent = new KEvent(context.Device.System); + BluetoothEventManager.UnknownBleDebugEvent = new KEvent(context.Device.System.KernelContext); if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.UnknownBleDebugEvent.ReadableEvent, out BluetoothEventManager.UnknownBleDebugEventHandle) != KernelResult.Success) { @@ -45,7 +45,7 @@ namespace Ryujinx.HLE.HOS.Services.Bluetooth if (BluetoothEventManager.RegisterBleDebugEventHandle == 0) { - BluetoothEventManager.RegisterBleDebugEvent = new KEvent(context.Device.System); + BluetoothEventManager.RegisterBleDebugEvent = new KEvent(context.Device.System.KernelContext); if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.RegisterBleDebugEvent.ReadableEvent, out BluetoothEventManager.RegisterBleDebugEventHandle) != KernelResult.Success) { @@ -59,7 +59,7 @@ namespace Ryujinx.HLE.HOS.Services.Bluetooth if (BluetoothEventManager.InitializeBleEventHandle == 0) { - BluetoothEventManager.InitializeBleEvent = new KEvent(context.Device.System); + BluetoothEventManager.InitializeBleEvent = new KEvent(context.Device.System.KernelContext); if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.InitializeBleEvent.ReadableEvent, out BluetoothEventManager.InitializeBleEventHandle) != KernelResult.Success) { @@ -69,7 +69,7 @@ namespace Ryujinx.HLE.HOS.Services.Bluetooth if (BluetoothEventManager.UnknownBleEventHandle == 0) { - BluetoothEventManager.UnknownBleEvent = new KEvent(context.Device.System); + BluetoothEventManager.UnknownBleEvent = new KEvent(context.Device.System.KernelContext); if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.UnknownBleEvent.ReadableEvent, out BluetoothEventManager.UnknownBleEventHandle) != KernelResult.Success) { @@ -79,7 +79,7 @@ namespace Ryujinx.HLE.HOS.Services.Bluetooth if (BluetoothEventManager.RegisterBleEventHandle == 0) { - BluetoothEventManager.RegisterBleEvent = new KEvent(context.Device.System); + BluetoothEventManager.RegisterBleEvent = new KEvent(context.Device.System.KernelContext); if (context.Process.HandleTable.GenerateHandle(BluetoothEventManager.RegisterBleEvent.ReadableEvent, out BluetoothEventManager.RegisterBleEventHandle) != KernelResult.Success) { diff --git a/Ryujinx.HLE/HOS/Services/BluetoothManager/BtmUser/IBtmUserCore.cs b/Ryujinx.HLE/HOS/Services/BluetoothManager/BtmUser/IBtmUserCore.cs index 47fdb88f7..769e224f0 100644 --- a/Ryujinx.HLE/HOS/Services/BluetoothManager/BtmUser/IBtmUserCore.cs +++ b/Ryujinx.HLE/HOS/Services/BluetoothManager/BtmUser/IBtmUserCore.cs @@ -29,7 +29,7 @@ namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser if (_bleScanEventHandle == 0) { - _bleScanEvent = new KEvent(context.Device.System); + _bleScanEvent = new KEvent(context.Device.System.KernelContext); result = context.Process.HandleTable.GenerateHandle(_bleScanEvent.ReadableEvent, out _bleScanEventHandle); @@ -55,7 +55,7 @@ namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser if (_bleConnectionEventHandle == 0) { - _bleConnectionEvent = new KEvent(context.Device.System); + _bleConnectionEvent = new KEvent(context.Device.System.KernelContext); result = context.Process.HandleTable.GenerateHandle(_bleConnectionEvent.ReadableEvent, out _bleConnectionEventHandle); @@ -81,7 +81,7 @@ namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser if (_bleServiceDiscoveryEventHandle == 0) { - _bleServiceDiscoveryEvent = new KEvent(context.Device.System); + _bleServiceDiscoveryEvent = new KEvent(context.Device.System.KernelContext); result = context.Process.HandleTable.GenerateHandle(_bleServiceDiscoveryEvent.ReadableEvent, out _bleServiceDiscoveryEventHandle); @@ -107,7 +107,7 @@ namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser if (_bleMtuConfigEventHandle == 0) { - _bleMtuConfigEvent = new KEvent(context.Device.System); + _bleMtuConfigEvent = new KEvent(context.Device.System.KernelContext); result = context.Process.HandleTable.GenerateHandle(_bleMtuConfigEvent.ReadableEvent, out _bleMtuConfigEventHandle); diff --git a/Ryujinx.HLE/HOS/Services/Friend/ServiceCreator/INotificationService.cs b/Ryujinx.HLE/HOS/Services/Friend/ServiceCreator/INotificationService.cs index 87d998c39..d4481a4e0 100644 --- a/Ryujinx.HLE/HOS/Services/Friend/ServiceCreator/INotificationService.cs +++ b/Ryujinx.HLE/HOS/Services/Friend/ServiceCreator/INotificationService.cs @@ -29,7 +29,7 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator _userId = userId; _permissionLevel = permissionLevel; _notifications = new LinkedList(); - _notificationEvent = new KEvent(context.Device.System); + _notificationEvent = new KEvent(context.Device.System.KernelContext); _hasNewFriendRequest = false; _hasFriendListUpdate = false; diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs index c4c9d095e..ef31e00db 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs @@ -58,7 +58,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid for (int i = 0; i < _styleSetUpdateEvents.Length; ++i) { - _styleSetUpdateEvents[i] = new KEvent(_device.System); + _styleSetUpdateEvents[i] = new KEvent(_device.System.KernelContext); } _fullBattery[0] = _fullBattery[1] = _fullBattery[2] = BatteryCharge.Percent100; diff --git a/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs b/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs index ec4a59df2..32ef28074 100644 --- a/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs +++ b/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs @@ -37,8 +37,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid public IHidServer(ServiceCtx context) { - _xpadIdEvent = new KEvent(context.Device.System); - _palmaOperationCompleteEvent = new KEvent(context.Device.System); + _xpadIdEvent = new KEvent(context.Device.System.KernelContext); + _palmaOperationCompleteEvent = new KEvent(context.Device.System.KernelContext); _npadJoyAssignmentMode = HidNpadJoyAssignmentMode.Dual; _npadHandheldActivationMode = HidNpadHandheldActivationMode.Dual; diff --git a/Ryujinx.HLE/HOS/Services/IpcService.cs b/Ryujinx.HLE/HOS/Services/IpcService.cs index 67df453e5..d13f3df87 100644 --- a/Ryujinx.HLE/HOS/Services/IpcService.cs +++ b/Ryujinx.HLE/HOS/Services/IpcService.cs @@ -168,7 +168,7 @@ namespace Ryujinx.HLE.HOS.Services } else { - KSession session = new KSession(context.Device.System); + KSession session = new KSession(context.Device.System.KernelContext); session.ClientSession.Service = obj; diff --git a/Ryujinx.HLE/HOS/Services/Ldn/NetworkInterface.cs b/Ryujinx.HLE/HOS/Services/Ldn/NetworkInterface.cs index f06c66446..10b70ab49 100644 --- a/Ryujinx.HLE/HOS/Services/Ldn/NetworkInterface.cs +++ b/Ryujinx.HLE/HOS/Services/Ldn/NetworkInterface.cs @@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn { // TODO(Ac_K): Determine where the internal state is set. NifmState = ResultCode.Success; - StateChangeEvent = new KEvent(system); + StateChangeEvent = new KEvent(system.KernelContext); _state = NetworkState.None; } diff --git a/Ryujinx.HLE/HOS/Services/Nfc/Nfp/UserManager/IUser.cs b/Ryujinx.HLE/HOS/Services/Nfc/Nfp/UserManager/IUser.cs index 91ed9391c..bc55d1a18 100644 --- a/Ryujinx.HLE/HOS/Services/Nfc/Nfp/UserManager/IUser.cs +++ b/Ryujinx.HLE/HOS/Services/Nfc/Nfp/UserManager/IUser.cs @@ -209,7 +209,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp { if (_devices[i].ActivateEventHandle == 0) { - _devices[i].ActivateEvent = new KEvent(context.Device.System); + _devices[i].ActivateEvent = new KEvent(context.Device.System.KernelContext); if (context.Process.HandleTable.GenerateHandle(_devices[i].ActivateEvent.ReadableEvent, out _devices[i].ActivateEventHandle) != KernelResult.Success) { @@ -238,7 +238,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp { if (_devices[i].DeactivateEventHandle == 0) { - _devices[i].DeactivateEvent = new KEvent(context.Device.System); + _devices[i].DeactivateEvent = new KEvent(context.Device.System.KernelContext); if (context.Process.HandleTable.GenerateHandle(_devices[i].DeactivateEvent.ReadableEvent, out _devices[i].DeactivateEventHandle) != KernelResult.Success) { @@ -317,7 +317,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp { if (_availabilityChangeEventHandle == 0) { - _availabilityChangeEvent = new KEvent(context.Device.System); + _availabilityChangeEvent = new KEvent(context.Device.System.KernelContext); if (context.Process.HandleTable.GenerateHandle(_availabilityChangeEvent.ReadableEvent, out _availabilityChangeEventHandle) != KernelResult.Success) { diff --git a/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs b/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs index c878c2d6a..cfc6b5169 100644 --- a/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs +++ b/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs @@ -15,8 +15,8 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService public IRequest(Horizon system, uint version) { - _event0 = new KEvent(system); - _event1 = new KEvent(system); + _event0 = new KEvent(system.KernelContext); + _event1 = new KEvent(system.KernelContext); _version = version; } diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostGpuDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostGpuDeviceFile.cs index 7eaa5cc58..523891404 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostGpuDeviceFile.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostGpuDeviceFile.cs @@ -13,9 +13,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel public NvHostGpuDeviceFile(ServiceCtx context) : base(context) { - _smExceptionBptIntReportEvent = new KEvent(context.Device.System); - _smExceptionBptPauseReportEvent = new KEvent(context.Device.System); - _errorNotifierEvent = new KEvent(context.Device.System); + _smExceptionBptIntReportEvent = new KEvent(context.Device.System.KernelContext); + _smExceptionBptPauseReportEvent = new KEvent(context.Device.System.KernelContext); + _errorNotifierEvent = new KEvent(context.Device.System.KernelContext); } public override NvInternalResult Ioctl2(NvIoctl command, Span arguments, Span inlineInBuffer) diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/Types/NvHostEvent.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/Types/NvHostEvent.cs index 03df77b16..a5f3539a2 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/Types/NvHostEvent.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/Types/NvHostEvent.cs @@ -35,7 +35,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl State = NvHostEventState.Available; - Event = new KEvent(system); + Event = new KEvent(system.KernelContext); _eventId = eventId; diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrlGpu/NvHostCtrlGpuDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrlGpu/NvHostCtrlGpuDeviceFile.cs index 53d4c98c6..a0b1f43c3 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrlGpu/NvHostCtrlGpuDeviceFile.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrlGpu/NvHostCtrlGpuDeviceFile.cs @@ -17,8 +17,8 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu public NvHostCtrlGpuDeviceFile(ServiceCtx context) : base(context) { - _errorEvent = new KEvent(context.Device.System); - _unknownEvent = new KEvent(context.Device.System); + _errorEvent = new KEvent(context.Device.System.KernelContext); + _unknownEvent = new KEvent(context.Device.System.KernelContext); } static NvHostCtrlGpuDeviceFile() diff --git a/Ryujinx.HLE/HOS/Services/Ptm/Psm/IPsmSession.cs b/Ryujinx.HLE/HOS/Services/Ptm/Psm/IPsmSession.cs index e41d6c376..4679b1547 100644 --- a/Ryujinx.HLE/HOS/Services/Ptm/Psm/IPsmSession.cs +++ b/Ryujinx.HLE/HOS/Services/Ptm/Psm/IPsmSession.cs @@ -12,7 +12,7 @@ namespace Ryujinx.HLE.HOS.Services.Ptm.Psm public IPsmSession(Horizon system) { - _stateChangeEvent = new KEvent(system); + _stateChangeEvent = new KEvent(system.KernelContext); _stateChangeEventHandle = -1; } diff --git a/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs b/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs index bcab5b17d..2a0624d57 100644 --- a/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs +++ b/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs @@ -32,7 +32,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm public static void InitializePort(Horizon system) { - KPort port = new KPort(system, 256, false, 0); + KPort port = new KPort(system.KernelContext, 256, false, 0); port.ClientPort.SetName("sm:"); @@ -64,7 +64,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm return ResultCode.InvalidName; } - KSession session = new KSession(context.Device.System); + KSession session = new KSession(context.Device.System.KernelContext); if (_registeredServices.TryGetValue(name, out KPort port)) { @@ -135,7 +135,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm Logger.PrintInfo(LogClass.ServiceSm, $"Register \"{name}\"."); - KPort port = new KPort(context.Device.System, maxSessions, isLight, 0); + KPort port = new KPort(context.Device.System.KernelContext, maxSessions, isLight, 0); if (!_registeredServices.TryAdd(name, port)) { diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs index 88b4025d4..efc252396 100644 --- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs +++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs @@ -60,8 +60,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger // TODO: CreateGraphicBufferAlloc? - _waitBufferFreeEvent = new KEvent(device.System); - _frameAvailableEvent = new KEvent(device.System); + _waitBufferFreeEvent = new KEvent(device.System.KernelContext); + _frameAvailableEvent = new KEvent(device.System.KernelContext); Owner = process; } diff --git a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardUserSystemClockCore.cs b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardUserSystemClockCore.cs index 42bc05fab..2499b549f 100644 --- a/Ryujinx.HLE/HOS/Services/Time/Clock/StandardUserSystemClockCore.cs +++ b/Ryujinx.HLE/HOS/Services/Time/Clock/StandardUserSystemClockCore.cs @@ -64,7 +64,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock internal void CreateAutomaticCorrectionEvent(Horizon system) { - _autoCorrectionEvent = new KEvent(system); + _autoCorrectionEvent = new KEvent(system.KernelContext); } public ResultCode SetAutomaticCorrectionEnabled(KThread thread, bool autoCorrectionEnabled) diff --git a/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs b/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs index d5b21f8c9..2e0d02124 100644 --- a/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs +++ b/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs @@ -106,7 +106,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService { if (_operationEventReadableHandle == 0) { - KEvent kEvent = new KEvent(context.Device.System); + KEvent kEvent = new KEvent(context.Device.System.KernelContext); _clockCore.RegisterOperationEvent(kEvent.WritableEvent); diff --git a/Ryujinx.HLE/HOS/SystemState/AppletStateMgr.cs b/Ryujinx.HLE/HOS/SystemState/AppletStateMgr.cs index 341f2a31b..14348a12f 100644 --- a/Ryujinx.HLE/HOS/SystemState/AppletStateMgr.cs +++ b/Ryujinx.HLE/HOS/SystemState/AppletStateMgr.cs @@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.SystemState { _messages = new ConcurrentQueue(); - MessageEvent = new KEvent(system); + MessageEvent = new KEvent(system.KernelContext); } public void SetFocus(bool isFocused)