فهرست منبع

IPC refactor part 2: Use ReplyAndReceive on HLE services and remove special handling from kernel (#1458)

* IPC refactor part 2: Use ReplyAndReceive on HLE services and remove special handling from kernel

* Fix for applet transfer memory + some nits

* Keep handles if possible to avoid server handle table exhaustion

* Fix IPC ZeroFill bug

* am: Correctly implement CreateManagedDisplayLayer and implement CreateManagedDisplaySeparableLayer

CreateManagedDisplaySeparableLayer is requires since 10.x+ when appletResourceUserId != 0

* Make it exit properly

* Make ServiceNotImplementedException show the full message again

* Allow yielding execution to avoid starving other threads

* Only wait if active

* Merge IVirtualMemoryManager and IAddressSpaceManager

* Fix Ro loading data from the wrong process

Co-authored-by: Thog <me@thog.eu>
gdkchan 5 سال پیش
والد
کامیت
cf6cd71488
100فایلهای تغییر یافته به همراه1638 افزوده شده و 1015 حذف شده
  1. 1 1
      ARMeilleure/State/ExecutionContext.cs
  2. 22 5
      Ryujinx.Audio.Renderer/Dsp/Command/AuxiliaryBufferCommand.cs
  3. 3 3
      Ryujinx.Audio.Renderer/Dsp/Command/CommandList.cs
  4. 2 2
      Ryujinx.Audio.Renderer/Dsp/DataSourceHelper.cs
  5. 5 5
      Ryujinx.Audio.Renderer/Dsp/State/AuxiliaryBufferHeader.cs
  6. 1 0
      Ryujinx.Audio.Renderer/Ryujinx.Audio.Renderer.csproj
  7. 10 10
      Ryujinx.Audio.Renderer/Server/AudioRenderSystem.cs
  8. 10 2
      Ryujinx.Audio.Renderer/Server/AudioRendererManager.cs
  9. 6 5
      Ryujinx.Cpu/MemoryHelper.cs
  10. 6 1
      Ryujinx.Cpu/MemoryManager.cs
  11. 1 1
      Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs
  12. 2 1
      Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs
  13. 11 9
      Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs
  14. 24 0
      Ryujinx.HLE/HOS/ArmProcessContext.cs
  15. 14 0
      Ryujinx.HLE/HOS/ArmProcessContextFactory.cs
  16. 14 6
      Ryujinx.HLE/HOS/Horizon.cs
  17. 20 3
      Ryujinx.HLE/HOS/Ipc/IpcMessage.cs
  18. 27 0
      Ryujinx.HLE/HOS/Ipc/IpcPtrBuffDesc.cs
  19. 6 0
      Ryujinx.HLE/HOS/Ipc/IpcRecvListBuffDesc.cs
  20. 11 0
      Ryujinx.HLE/HOS/Kernel/Common/OnScopeExit.cs
  21. 2 2
      Ryujinx.HLE/HOS/Kernel/Ipc/KBufferDescriptorTable.cs
  22. 0 9
      Ryujinx.HLE/HOS/Kernel/Ipc/KClientPort.cs
  23. 0 9
      Ryujinx.HLE/HOS/Kernel/Ipc/KClientSession.cs
  24. 13 21
      Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs
  25. 1 14
      Ryujinx.HLE/HOS/Kernel/Ipc/KSession.cs
  26. 1 1
      Ryujinx.HLE/HOS/Kernel/KernelContext.cs
  27. 38 0
      Ryujinx.HLE/HOS/Kernel/KernelStatic.cs
  28. 8 8
      Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlock.cs
  29. 4 4
      Ryujinx.HLE/HOS/Kernel/Memory/KMemoryInfo.cs
  30. 176 151
      Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs
  31. 6 6
      Ryujinx.HLE/HOS/Kernel/Memory/KSharedMemory.cs
  32. 5 2
      Ryujinx.HLE/HOS/Kernel/Memory/KTransferMemory.cs
  33. 1 1
      Ryujinx.HLE/HOS/Kernel/Memory/MemoryPermission.cs
  34. 5 5
      Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs
  35. 13 0
      Ryujinx.HLE/HOS/Kernel/Process/IProcessContext.cs
  36. 10 0
      Ryujinx.HLE/HOS/Kernel/Process/IProcessContextFactory.cs
  37. 97 137
      Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs
  38. 14 13
      Ryujinx.HLE/HOS/Kernel/Process/KProcessCapabilities.cs
  39. 25 0
      Ryujinx.HLE/HOS/Kernel/Process/ProcessContext.cs
  40. 13 0
      Ryujinx.HLE/HOS/Kernel/Process/ProcessContextFactory.cs
  41. 38 0
      Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationFlags.cs
  42. 23 23
      Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationInfo.cs
  43. 184 89
      Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs
  44. 5 5
      Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs
  45. 5 5
      Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs
  46. 2 0
      Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs
  47. 50 40
      Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs
  48. 18 12
      Ryujinx.HLE/HOS/ProgramLoader.cs
  49. 24 28
      Ryujinx.HLE/HOS/ServiceCtx.cs
  50. 8 3
      Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs
  51. 25 12
      Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs
  52. 18 10
      Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs
  53. 7 3
      Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs
  54. 3 1
      Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs
  55. 37 5
      Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs
  56. 9 2
      Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IWindowController.cs
  57. 1 1
      Ryujinx.HLE/HOS/Services/Am/AppletAE/IAllSystemAppletProxiesService.cs
  58. 27 16
      Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs
  59. 8 3
      Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs
  60. 1 1
      Ryujinx.HLE/HOS/Services/Am/AppletOE/IApplicationProxyService.cs
  61. 14 8
      Ryujinx.HLE/HOS/Services/Audio/AudioOutManager/IAudioOut.cs
  62. 3 1
      Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager.cs
  63. 4 2
      Ryujinx.HLE/HOS/Services/Audio/AudioRendererManagerServer.cs
  64. 2 1
      Ryujinx.HLE/HOS/Services/Audio/IAudioInManager.cs
  65. 2 2
      Ryujinx.HLE/HOS/Services/Audio/IAudioOutManager.cs
  66. 3 0
      Ryujinx.HLE/HOS/Services/Audio/IHardwareOpusDecoderManager.cs
  67. 7 3
      Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs
  68. 6 16
      Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs
  69. 7 3
      Ryujinx.HLE/HOS/Services/Hid/HidServer/IAppletResource.cs
  70. 12 12
      Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs
  71. 24 38
      Ryujinx.HLE/HOS/Services/IpcService.cs
  72. 16 16
      Ryujinx.HLE/HOS/Services/Nfc/Nfp/UserManager/IUser.cs
  73. 15 6
      Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs
  74. 8 3
      Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessor.cs
  75. 11 6
      Ryujinx.HLE/HOS/Services/Ns/IAddOnContentManager.cs
  76. 35 32
      Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs
  77. 3 4
      Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvDeviceFile.cs
  78. 2 1
      Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs
  79. 5 4
      Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs
  80. 3 2
      Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostGpuDeviceFile.cs
  81. 3 3
      Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs
  82. 3 2
      Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrlGpu/NvHostCtrlGpuDeviceFile.cs
  83. 12 12
      Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvMap/NvMapDeviceFile.cs
  84. 19 18
      Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs
  85. 8 3
      Ryujinx.HLE/HOS/Services/Sdb/Pl/ISharedFontManager.cs
  86. 184 49
      Ryujinx.HLE/HOS/Services/ServerBase.cs
  87. 8 20
      Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs
  88. 4 1
      Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs
  89. 10 10
      Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs
  90. 6 6
      Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueue.cs
  91. 39 6
      Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs
  92. 5 0
      Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs
  93. 1 1
      Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs
  94. 15 11
      Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs
  95. 6 6
      Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/GraphicBuffer.cs
  96. 3 1
      Ryujinx.HLE/HOS/Services/Time/IStaticServiceForGlue.cs
  97. 6 6
      Ryujinx.HLE/HOS/Services/Time/ITimeServiceManager.cs
  98. 1 2
      Ryujinx.HLE/HOS/Services/Vi/IApplicationRootService.cs
  99. 1 1
      Ryujinx.HLE/HOS/Services/Vi/IManagerRootService.cs
  100. 1 1
      Ryujinx.HLE/HOS/Services/Vi/ISystemRootService.cs

+ 1 - 1
ARMeilleure/State/ExecutionContext.cs

@@ -66,7 +66,7 @@ namespace ARMeilleure.State
             }
             }
         }
         }
 
 
-        internal bool Running { get; private set; }
+        public bool Running { get; private set; }
 
 
         public event EventHandler<EventArgs>              Interrupt;
         public event EventHandler<EventArgs>              Interrupt;
         public event EventHandler<InstExceptionEventArgs> Break;
         public event EventHandler<InstExceptionEventArgs> Break;

+ 22 - 5
Ryujinx.Audio.Renderer/Dsp/Command/AuxiliaryBufferCommand.cs

@@ -16,7 +16,7 @@
 //
 //
 
 
 using Ryujinx.Audio.Renderer.Common;
 using Ryujinx.Audio.Renderer.Common;
-using Ryujinx.Cpu;
+using Ryujinx.Memory;
 using System;
 using System;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
@@ -65,7 +65,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
             IsEffectEnabled = isEnabled;
             IsEffectEnabled = isEnabled;
         }
         }
 
 
-        private uint Read(MemoryManager memoryManager, ulong bufferAddress, uint countMax, Span<int> outBuffer, uint count, uint readOffset, uint updateCount)
+        private uint Read(IVirtualMemoryManager memoryManager, ulong bufferAddress, uint countMax, Span<int> outBuffer, uint count, uint readOffset, uint updateCount)
         {
         {
             if (countMax == 0 || bufferAddress == 0)
             if (countMax == 0 || bufferAddress == 0)
             {
             {
@@ -104,7 +104,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
             return count;
             return count;
         }
         }
 
 
-        private uint Write(MemoryManager memoryManager, ulong outBufferAddress, uint countMax, ReadOnlySpan<int> buffer, uint count, uint writeOffset, uint updateCount)
+        private uint Write(IVirtualMemoryManager memoryManager, ulong outBufferAddress, uint countMax, ReadOnlySpan<int> buffer, uint count, uint writeOffset, uint updateCount)
         {
         {
             if (countMax == 0 || outBufferAddress == 0)
             if (countMax == 0 || outBufferAddress == 0)
             {
             {
@@ -175,8 +175,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
             }
             }
             else
             else
             {
             {
-                MemoryHelper.FillWithZeros(context.MemoryManager, (long)BufferInfo.SendBufferInfo, Unsafe.SizeOf<AuxiliaryBufferInfo>());
-                MemoryHelper.FillWithZeros(context.MemoryManager, (long)BufferInfo.ReturnBufferInfo, Unsafe.SizeOf<AuxiliaryBufferInfo>());
+                ZeroFill(context.MemoryManager, BufferInfo.SendBufferInfo, Unsafe.SizeOf<AuxiliaryBufferInfo>());
+                ZeroFill(context.MemoryManager, BufferInfo.ReturnBufferInfo, Unsafe.SizeOf<AuxiliaryBufferInfo>());
 
 
                 if (InputBufferIndex != OutputBufferIndex)
                 if (InputBufferIndex != OutputBufferIndex)
                 {
                 {
@@ -184,5 +184,22 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
                 }
                 }
             }
             }
         }
         }
+
+        private static void ZeroFill(IVirtualMemoryManager memoryManager, ulong address, int size)
+        {
+            ulong endAddress = address + (ulong)size;
+
+            while (address + 7UL < endAddress)
+            {
+                memoryManager.Write(address, 0UL);
+                address += 8;
+            }
+
+            while (address < endAddress)
+            {
+                memoryManager.Write(address, (byte)0);
+                address++;
+            }
+        }
     }
     }
 }
 }

+ 3 - 3
Ryujinx.Audio.Renderer/Dsp/Command/CommandList.cs

@@ -19,7 +19,7 @@ using Ryujinx.Audio.Renderer.Integration;
 using Ryujinx.Audio.Renderer.Server;
 using Ryujinx.Audio.Renderer.Server;
 using Ryujinx.Common;
 using Ryujinx.Common;
 using Ryujinx.Common.Logging;
 using Ryujinx.Common.Logging;
-using Ryujinx.Cpu;
+using Ryujinx.Memory;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 
 
@@ -37,7 +37,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
 
 
         public List<ICommand> Commands { get; }
         public List<ICommand> Commands { get; }
 
 
-        public MemoryManager MemoryManager { get; }
+        public IVirtualMemoryManager MemoryManager { get; }
 
 
         public HardwareDevice OutputDevice { get; private set; }
         public HardwareDevice OutputDevice { get; private set; }
 
 
@@ -50,7 +50,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
         {
         {
         }
         }
 
 
-        public CommandList(MemoryManager memoryManager, Memory<float> mixBuffer, uint sampleCount, uint sampleRate, uint mixBufferCount, uint voiceChannelCountMax)
+        public CommandList(IVirtualMemoryManager memoryManager, Memory<float> mixBuffer, uint sampleCount, uint sampleRate, uint mixBufferCount, uint voiceChannelCountMax)
         {
         {
             SampleCount = sampleCount;
             SampleCount = sampleCount;
             SampleRate = sampleRate;
             SampleRate = sampleRate;

+ 2 - 2
Ryujinx.Audio.Renderer/Dsp/DataSourceHelper.cs

@@ -18,7 +18,7 @@
 using Ryujinx.Audio.Renderer.Common;
 using Ryujinx.Audio.Renderer.Common;
 using Ryujinx.Audio.Renderer.Dsp.State;
 using Ryujinx.Audio.Renderer.Dsp.State;
 using Ryujinx.Common.Logging;
 using Ryujinx.Common.Logging;
-using Ryujinx.Cpu;
+using Ryujinx.Memory;
 using System;
 using System;
 using System.Buffers;
 using System.Buffers;
 using System.Diagnostics;
 using System.Diagnostics;
@@ -63,7 +63,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
             }
             }
         }
         }
 
 
-        public static void ProcessWaveBuffers(MemoryManager memoryManager, Span<float> outputBuffer, WaveBufferInformation info, uint targetSampleRate, int sampleCount)
+        public static void ProcessWaveBuffers(IVirtualMemoryManager memoryManager, Span<float> outputBuffer, WaveBufferInformation info, uint targetSampleRate, int sampleCount)
         {
         {
             const int tempBufferSize = 0x3F00;
             const int tempBufferSize = 0x3F00;
 
 

+ 5 - 5
Ryujinx.Audio.Renderer/Dsp/State/AuxiliaryBufferHeader.cs

@@ -15,7 +15,7 @@
 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 //
 //
 
 
-using Ryujinx.Cpu;
+using Ryujinx.Memory;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
 
 
 namespace Ryujinx.Audio.Renderer.Dsp.State
 namespace Ryujinx.Audio.Renderer.Dsp.State
@@ -33,22 +33,22 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
             public uint WriteOffset;
             public uint WriteOffset;
             private uint _reserved;
             private uint _reserved;
 
 
-            public static uint GetReadOffset(MemoryManager manager, ulong bufferAddress)
+            public static uint GetReadOffset(IVirtualMemoryManager manager, ulong bufferAddress)
             {
             {
                 return manager.Read<uint>(bufferAddress + ReadOffsetPosition);
                 return manager.Read<uint>(bufferAddress + ReadOffsetPosition);
             }
             }
 
 
-            public static uint GetWriteOffset(MemoryManager manager, ulong bufferAddress)
+            public static uint GetWriteOffset(IVirtualMemoryManager manager, ulong bufferAddress)
             {
             {
                 return manager.Read<uint>(bufferAddress + WriteOffsetPosition);
                 return manager.Read<uint>(bufferAddress + WriteOffsetPosition);
             }
             }
 
 
-            public static void SetReadOffset(MemoryManager manager, ulong bufferAddress, uint value)
+            public static void SetReadOffset(IVirtualMemoryManager manager, ulong bufferAddress, uint value)
             {
             {
                 manager.Write(bufferAddress + ReadOffsetPosition, value);
                 manager.Write(bufferAddress + ReadOffsetPosition, value);
             }
             }
 
 
-            public static void SetWriteOffset(MemoryManager manager, ulong bufferAddress, uint value)
+            public static void SetWriteOffset(IVirtualMemoryManager manager, ulong bufferAddress, uint value)
             {
             {
                 manager.Write(bufferAddress + WriteOffsetPosition, value);
                 manager.Write(bufferAddress + WriteOffsetPosition, value);
             }
             }

+ 1 - 0
Ryujinx.Audio.Renderer/Ryujinx.Audio.Renderer.csproj

@@ -8,6 +8,7 @@
   <ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
     <ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
     <ProjectReference Include="..\Ryujinx.Cpu\Ryujinx.Cpu.csproj" />
     <ProjectReference Include="..\Ryujinx.Cpu\Ryujinx.Cpu.csproj" />
+    <ProjectReference Include="..\Ryujinx.Memory\Ryujinx.Memory.csproj" />
   </ItemGroup>
   </ItemGroup>
 
 
 </Project>
 </Project>

+ 10 - 10
Ryujinx.Audio.Renderer/Server/AudioRenderSystem.cs

@@ -31,7 +31,7 @@ using Ryujinx.Audio.Renderer.Server.Voice;
 using Ryujinx.Audio.Renderer.Utils;
 using Ryujinx.Audio.Renderer.Utils;
 using Ryujinx.Common;
 using Ryujinx.Common;
 using Ryujinx.Common.Logging;
 using Ryujinx.Common.Logging;
-using Ryujinx.Cpu;
+using Ryujinx.Memory;
 using System;
 using System;
 using System.Buffers;
 using System.Buffers;
 using System.Diagnostics;
 using System.Diagnostics;
@@ -87,7 +87,7 @@ namespace Ryujinx.Audio.Renderer.Server
 
 
         private Memory<byte> _performanceBuffer;
         private Memory<byte> _performanceBuffer;
 
 
-        public MemoryManager MemoryManager { get; private set; }
+        public IVirtualMemoryManager MemoryManager { get; private set; }
 
 
         private ulong _elapsedFrameCount;
         private ulong _elapsedFrameCount;
         private ulong _renderingStartTick;
         private ulong _renderingStartTick;
@@ -96,14 +96,14 @@ namespace Ryujinx.Audio.Renderer.Server
 
 
         public AudioRenderSystem(AudioRendererManager manager, IWritableEvent systemEvent)
         public AudioRenderSystem(AudioRendererManager manager, IWritableEvent systemEvent)
         {
         {
-            _manager           = manager;
-            _terminationEvent  = new ManualResetEvent(false);
+            _manager            = manager;
+            _terminationEvent   = new ManualResetEvent(false);
             _dspMemoryPoolState = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
             _dspMemoryPoolState = MemoryPoolState.Create(MemoryPoolState.LocationType.Dsp);
-            _voiceContext      = new VoiceContext();
-            _mixContext        = new MixContext();
-            _sinkContext       = new SinkContext();
-            _splitterContext   = new SplitterContext();
-            _effectContext     = new EffectContext();
+            _voiceContext       = new VoiceContext();
+            _mixContext         = new MixContext();
+            _sinkContext        = new SinkContext();
+            _splitterContext    = new SplitterContext();
+            _effectContext      = new EffectContext();
 
 
             _commandProcessingTimeEstimator = null;
             _commandProcessingTimeEstimator = null;
             _systemEvent = systemEvent;
             _systemEvent = systemEvent;
@@ -113,7 +113,7 @@ namespace Ryujinx.Audio.Renderer.Server
             _sessionId                 = 0;
             _sessionId                 = 0;
         }
         }
 
 
-        public ResultCode Initialize(ref AudioRendererConfiguration parameter, uint processHandle, CpuAddress workBuffer, ulong workBufferSize, int sessionId, ulong appletResourceId, MemoryManager memoryManager)
+        public ResultCode Initialize(ref AudioRendererConfiguration parameter, uint processHandle, CpuAddress workBuffer, ulong workBufferSize, int sessionId, ulong appletResourceId, IVirtualMemoryManager memoryManager)
         {
         {
             if (!BehaviourContext.CheckValidRevision(parameter.Revision))
             if (!BehaviourContext.CheckValidRevision(parameter.Revision))
             {
             {

+ 10 - 2
Ryujinx.Audio.Renderer/Server/AudioRendererManager.cs

@@ -19,7 +19,7 @@ using Ryujinx.Audio.Renderer.Dsp;
 using Ryujinx.Audio.Renderer.Integration;
 using Ryujinx.Audio.Renderer.Integration;
 using Ryujinx.Audio.Renderer.Parameter;
 using Ryujinx.Audio.Renderer.Parameter;
 using Ryujinx.Common.Logging;
 using Ryujinx.Common.Logging;
-using Ryujinx.Cpu;
+using Ryujinx.Memory;
 using System;
 using System;
 using System.Diagnostics;
 using System.Diagnostics;
 using System.Threading;
 using System.Threading;
@@ -288,7 +288,7 @@ namespace Ryujinx.Audio.Renderer.Server
         /// <param name="workBufferSize">The guest work buffer size.</param>
         /// <param name="workBufferSize">The guest work buffer size.</param>
         /// <param name="processHandle">The process handle of the application.</param>
         /// <param name="processHandle">The process handle of the application.</param>
         /// <returns>A <see cref="ResultCode"/> reporting an error or a success.</returns>
         /// <returns>A <see cref="ResultCode"/> reporting an error or a success.</returns>
-        public ResultCode OpenAudioRenderer(out AudioRenderSystem renderer, MemoryManager memoryManager, ref AudioRendererConfiguration parameter, ulong appletResourceUserId, ulong workBufferAddress, ulong workBufferSize, uint processHandle)
+        public ResultCode OpenAudioRenderer(out AudioRenderSystem renderer, IVirtualMemoryManager memoryManager, ref AudioRendererConfiguration parameter, ulong appletResourceUserId, ulong workBufferAddress, ulong workBufferSize, uint processHandle)
         {
         {
             int sessionId = AcquireSessionId();
             int sessionId = AcquireSessionId();
 
 
@@ -321,6 +321,14 @@ namespace Ryujinx.Audio.Renderer.Server
         {
         {
             if (disposing)
             if (disposing)
             {
             {
+                lock (_audioProcessorLock)
+                {
+                    if (_isRunning)
+                    {
+                        StopLocked();
+                    }
+                }
+
                 Processor.Dispose();
                 Processor.Dispose();
 
 
                 foreach (HardwareDevice device in OutputDevices)
                 foreach (HardwareDevice device in OutputDevices)

+ 6 - 5
Ryujinx.Cpu/MemoryHelper.cs

@@ -1,4 +1,5 @@
-using System;
+using Ryujinx.Memory;
+using System;
 using System.IO;
 using System.IO;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
 using System.Text;
 using System.Text;
@@ -7,7 +8,7 @@ namespace Ryujinx.Cpu
 {
 {
     public static class MemoryHelper
     public static class MemoryHelper
     {
     {
-        public static void FillWithZeros(MemoryManager memory, long position, int size)
+        public static void FillWithZeros(IVirtualMemoryManager memory, long position, int size)
         {
         {
             int size8 = size & ~(8 - 1);
             int size8 = size & ~(8 - 1);
 
 
@@ -22,7 +23,7 @@ namespace Ryujinx.Cpu
             }
             }
         }
         }
 
 
-        public unsafe static T Read<T>(MemoryManager memory, long position) where T : struct
+        public unsafe static T Read<T>(IVirtualMemoryManager memory, long position) where T : struct
         {
         {
             long size = Marshal.SizeOf<T>();
             long size = Marshal.SizeOf<T>();
 
 
@@ -36,7 +37,7 @@ namespace Ryujinx.Cpu
             }
             }
         }
         }
 
 
-        public unsafe static void Write<T>(MemoryManager memory, long position, T value) where T : struct
+        public unsafe static void Write<T>(IVirtualMemoryManager memory, long position, T value) where T : struct
         {
         {
             long size = Marshal.SizeOf<T>();
             long size = Marshal.SizeOf<T>();
 
 
@@ -50,7 +51,7 @@ namespace Ryujinx.Cpu
             memory.Write((ulong)position, data);
             memory.Write((ulong)position, data);
         }
         }
 
 
-        public static string ReadAsciiString(MemoryManager memory, long position, long maxSize = -1)
+        public static string ReadAsciiString(IVirtualMemoryManager memory, long position, long maxSize = -1)
         {
         {
             using (MemoryStream ms = new MemoryStream())
             using (MemoryStream ms = new MemoryStream())
             {
             {

+ 6 - 1
Ryujinx.Cpu/MemoryManager.cs

@@ -13,7 +13,7 @@ namespace Ryujinx.Cpu
     /// <summary>
     /// <summary>
     /// Represents a CPU memory manager.
     /// Represents a CPU memory manager.
     /// </summary>
     /// </summary>
-    public sealed class MemoryManager : IMemoryManager, IDisposable, IVirtualMemoryManager
+    public sealed class MemoryManager : IMemoryManager, IVirtualMemoryManager, IDisposable
     {
     {
         public const int PageBits = 12;
         public const int PageBits = 12;
         public const int PageSize = 1 << PageBits;
         public const int PageSize = 1 << PageBits;
@@ -468,6 +468,11 @@ namespace Ryujinx.Cpu
         /// <returns>True if the entire range is mapped, false otherwise</returns>
         /// <returns>True if the entire range is mapped, false otherwise</returns>
         public bool IsRangeMapped(ulong va, ulong size)
         public bool IsRangeMapped(ulong va, ulong size)
         {
         {
+            if (size == 0UL)
+            {
+                return true;
+            }
+
             ulong endVa = (va + size + PageMask) & ~(ulong)PageMask;
             ulong endVa = (va + size + PageMask) & ~(ulong)PageMask;
 
 
             va &= ~(ulong)PageMask;
             va &= ~(ulong)PageMask;

+ 1 - 1
Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs

@@ -1,4 +1,4 @@
-using Ryujinx.Cpu;
+using Ryujinx.Memory;
 using System;
 using System;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;

+ 2 - 1
Ryujinx.Graphics.Gpu/Memory/PhysicalMemory.cs

@@ -1,5 +1,6 @@
 using Ryujinx.Cpu;
 using Ryujinx.Cpu;
 using Ryujinx.Cpu.Tracking;
 using Ryujinx.Cpu.Tracking;
+using Ryujinx.Memory;
 using System;
 using System;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
@@ -12,7 +13,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
     /// </summary>
     /// </summary>
     class PhysicalMemory
     class PhysicalMemory
     {
     {
-        public const int PageSize = Cpu.MemoryManager.PageSize;
+        public const int PageSize = 0x1000;
 
 
         private readonly Cpu.MemoryManager _cpuMemory;
         private readonly Cpu.MemoryManager _cpuMemory;
 
 

+ 11 - 9
Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs

@@ -14,28 +14,31 @@ namespace Ryujinx.HLE.Exceptions
     [Serializable]
     [Serializable]
     internal class ServiceNotImplementedException : Exception
     internal class ServiceNotImplementedException : Exception
     {
     {
+        public IIpcService Service { get; }
         public ServiceCtx Context { get; }
         public ServiceCtx Context { get; }
         public IpcMessage Request { get; }
         public IpcMessage Request { get; }
 
 
-        public ServiceNotImplementedException(ServiceCtx context)
-            : this(context, "The service call is not implemented.")
+        public ServiceNotImplementedException(IIpcService service, ServiceCtx context)
+            : this(service, context, "The service call is not implemented.")
         { }
         { }
 
 
-        public ServiceNotImplementedException(ServiceCtx context, string message)
+        public ServiceNotImplementedException(IIpcService service, ServiceCtx context, string message)
             : base(message)
             : base(message)
         {
         {
+            Service = service;
             Context = context;
             Context = context;
             Request = context.Request;
             Request = context.Request;
         }
         }
 
 
-        public ServiceNotImplementedException(ServiceCtx context, string message, Exception inner)
+        public ServiceNotImplementedException(IIpcService service, ServiceCtx context, string message, Exception inner)
             : base(message, inner)
             : base(message, inner)
         {
         {
+            Service = service;
             Context = context;
             Context = context;
             Request = context.Request;
             Request = context.Request;
         }
         }
 
 
-        protected ServiceNotImplementedException(SerializationInfo info, StreamingContext context) 
+        protected ServiceNotImplementedException(SerializationInfo info, StreamingContext context)
             : base(info, context)
             : base(info, context)
         { }
         { }
 
 
@@ -59,17 +62,16 @@ namespace Ryujinx.HLE.Exceptions
 
 
             if (callingType != null && callingMethod != null)
             if (callingType != null && callingMethod != null)
             {
             {
-                var ipcService  = Context.Session.Service;
-                var ipcCommands = ipcService.Commands;
+                var ipcCommands = Service.Commands;
 
 
                 // Find the handler for the method called
                 // Find the handler for the method called
-                var ipcHandler   = ipcCommands.FirstOrDefault(x => x.Value as MethodBase == callingMethod);
+                var ipcHandler   = ipcCommands.FirstOrDefault(x => x.Value == callingMethod);
                 var ipcCommandId = ipcHandler.Key;
                 var ipcCommandId = ipcHandler.Key;
                 var ipcMethod    = ipcHandler.Value;
                 var ipcMethod    = ipcHandler.Value;
 
 
                 if (ipcMethod != null)
                 if (ipcMethod != null)
                 {
                 {
-                    sb.AppendLine($"Service Command: {ipcService.GetType().FullName}: {ipcCommandId} ({ipcMethod.Name})");
+                    sb.AppendLine($"Service Command: {Service.GetType().FullName}: {ipcCommandId} ({ipcMethod.Name})");
                     sb.AppendLine();
                     sb.AppendLine();
                 }
                 }
             }
             }

+ 24 - 0
Ryujinx.HLE/HOS/ArmProcessContext.cs

@@ -0,0 +1,24 @@
+using ARMeilleure.State;
+using Ryujinx.Cpu;
+using Ryujinx.HLE.HOS.Kernel.Process;
+using Ryujinx.Memory;
+
+namespace Ryujinx.HLE.HOS
+{
+    class ArmProcessContext : IProcessContext
+    {
+        private readonly MemoryManager _memoryManager;
+        private readonly CpuContext _cpuContext;
+
+        public IVirtualMemoryManager AddressSpace => _memoryManager;
+
+        public ArmProcessContext(MemoryManager memoryManager)
+        {
+            _memoryManager = memoryManager;
+            _cpuContext = new CpuContext(memoryManager);
+        }
+
+        public void Execute(ExecutionContext context, ulong codeAddress) => _cpuContext.Execute(context, codeAddress);
+        public void Dispose() => _memoryManager.Dispose();
+    }
+}

+ 14 - 0
Ryujinx.HLE/HOS/ArmProcessContextFactory.cs

@@ -0,0 +1,14 @@
+using Ryujinx.Cpu;
+using Ryujinx.HLE.HOS.Kernel.Process;
+using Ryujinx.Memory;
+
+namespace Ryujinx.HLE.HOS
+{
+    class ArmProcessContextFactory : IProcessContextFactory
+    {
+        public IProcessContext Create(MemoryBlock backingMemory, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler)
+        {
+            return new ArmProcessContext(new MemoryManager(backingMemory, addressSpaceSize, invalidAccessHandler));
+        }
+    }
+}

+ 14 - 6
Ryujinx.HLE/HOS/Horizon.cs

@@ -120,11 +120,11 @@ namespace Ryujinx.HLE.HOS
             iirsPageList.AddRange(iirsPa, IirsSize / KMemoryManager.PageSize);
             iirsPageList.AddRange(iirsPa, IirsSize / KMemoryManager.PageSize);
             timePageList.AddRange(timePa, TimeSize / KMemoryManager.PageSize);
             timePageList.AddRange(timePa, TimeSize / KMemoryManager.PageSize);
 
 
-            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);
+            HidSharedMem  = new KSharedMemory(KernelContext, hidPageList,  0, 0, KMemoryPermission.Read);
+            FontSharedMem = new KSharedMemory(KernelContext, fontPageList, 0, 0, KMemoryPermission.Read);
+            IirsSharedMem = new KSharedMemory(KernelContext, iirsPageList, 0, 0, KMemoryPermission.Read);
 
 
-            KSharedMemory timeSharedMemory = new KSharedMemory(KernelContext, timePageList, 0, 0, MemoryPermission.Read);
+            KSharedMemory timeSharedMemory = new KSharedMemory(KernelContext, timePageList, 0, 0, KMemoryPermission.Read);
 
 
             TimeServiceManager.Instance.Initialize(device, this, timeSharedMemory, timePa - DramMemoryMap.DramBase, TimeSize);
             TimeServiceManager.Instance.Initialize(device, this, timeSharedMemory, timePa - DramMemoryMap.DramBase, TimeSize);
 
 
@@ -134,8 +134,6 @@ namespace Ryujinx.HLE.HOS
 
 
             Font = new SharedFontManager(device, fontPa - DramMemoryMap.DramBase);
             Font = new SharedFontManager(device, fontPa - DramMemoryMap.DramBase);
 
 
-            IUserInterface.InitializePort(this);
-
             VsyncEvent = new KEvent(KernelContext);
             VsyncEvent = new KEvent(KernelContext);
 
 
             DisplayResolutionChangeEvent = new KEvent(KernelContext);
             DisplayResolutionChangeEvent = new KEvent(KernelContext);
@@ -224,6 +222,16 @@ namespace Ryujinx.HLE.HOS
             AudioRendererManager.Initialize(writableEvents, devices);
             AudioRendererManager.Initialize(writableEvents, devices);
         }
         }
 
 
+        public void InitializeServices()
+        {
+            IUserInterface sm = new IUserInterface(KernelContext);
+
+            // Wait until SM server thread is done with initialization,
+            // only then doing connections to SM is safe.
+            sm.Server.InitDone.WaitOne();
+            sm.Server.InitDone.Dispose();
+        }
+
         public void LoadKip(string kipPath)
         public void LoadKip(string kipPath)
         {
         {
             using IStorage kipFile = new LocalStorage(kipPath, FileAccess.Read);
             using IStorage kipFile = new LocalStorage(kipPath, FileAccess.Read);

+ 20 - 3
Ryujinx.HLE/HOS/Ipc/IpcMessage.cs

@@ -84,6 +84,11 @@ namespace Ryujinx.HLE.HOS.Ipc
 
 
             long pad0 = GetPadSize16(reader.BaseStream.Position + cmdPtr);
             long pad0 = GetPadSize16(reader.BaseStream.Position + cmdPtr);
 
 
+            if (rawDataSize != 0)
+            {
+                rawDataSize -= (int)pad0;
+            }
+
             reader.BaseStream.Seek(pad0, SeekOrigin.Current);
             reader.BaseStream.Seek(pad0, SeekOrigin.Current);
 
 
             int recvListCount = recvListFlags - 2;
             int recvListCount = recvListFlags - 2;
@@ -107,7 +112,7 @@ namespace Ryujinx.HLE.HOS.Ipc
             }
             }
         }
         }
 
 
-        public byte[] GetBytes(long cmdPtr)
+        public byte[] GetBytes(long cmdPtr, ulong recvListAddr)
         {
         {
             using (MemoryStream ms = new MemoryStream())
             using (MemoryStream ms = new MemoryStream())
             {
             {
@@ -131,7 +136,11 @@ namespace Ryujinx.HLE.HOS.Ipc
 
 
                 int dataLength = RawData?.Length ?? 0;
                 int dataLength = RawData?.Length ?? 0;
 
 
-                int pad0 = (int)GetPadSize16(cmdPtr + 8 + handleData.Length);
+                dataLength = (dataLength + 3) & ~3;
+
+                int rawLength = dataLength;
+
+                int pad0 = (int)GetPadSize16(cmdPtr + 8 + handleData.Length + PtrBuff.Count * 8);
 
 
                 // Apparently, padding after Raw Data is 16 bytes, however when there is
                 // Apparently, padding after Raw Data is 16 bytes, however when there is
                 // padding before Raw Data too, we need to subtract the size of this padding.
                 // padding before Raw Data too, we need to subtract the size of this padding.
@@ -140,7 +149,7 @@ namespace Ryujinx.HLE.HOS.Ipc
 
 
                 dataLength = (dataLength + pad0 + pad1) / 4;
                 dataLength = (dataLength + pad0 + pad1) / 4;
 
 
-                word1 = dataLength & 0x3ff;
+                word1 = (dataLength & 0x3ff) | (2 << 10);
 
 
                 if (HandleDesc != null)
                 if (HandleDesc != null)
                 {
                 {
@@ -151,14 +160,22 @@ namespace Ryujinx.HLE.HOS.Ipc
                 writer.Write(word1);
                 writer.Write(word1);
                 writer.Write(handleData);
                 writer.Write(handleData);
 
 
+                for (int index = 0; index < PtrBuff.Count; index++)
+                {
+                    writer.Write(PtrBuff[index].GetWord0());
+                    writer.Write(PtrBuff[index].GetWord1());
+                }
+
                 ms.Seek(pad0, SeekOrigin.Current);
                 ms.Seek(pad0, SeekOrigin.Current);
 
 
                 if (RawData != null)
                 if (RawData != null)
                 {
                 {
                     writer.Write(RawData);
                     writer.Write(RawData);
+                    ms.Seek(rawLength - RawData.Length, SeekOrigin.Current);
                 }
                 }
 
 
                 writer.Write(new byte[pad1]);
                 writer.Write(new byte[pad1]);
+                writer.Write(recvListAddr);
 
 
                 return ms.ToArray();
                 return ms.ToArray();
             }
             }

+ 27 - 0
Ryujinx.HLE/HOS/Ipc/IpcPtrBuffDesc.cs

@@ -8,6 +8,13 @@ namespace Ryujinx.HLE.HOS.Ipc
         public int   Index    { get; private set; }
         public int   Index    { get; private set; }
         public long  Size     { get; private set; }
         public long  Size     { get; private set; }
 
 
+        public IpcPtrBuffDesc(long position, int index, long size)
+        {
+            Position = position;
+            Index = index;
+            Size = size;
+        }
+
         public IpcPtrBuffDesc(BinaryReader reader)
         public IpcPtrBuffDesc(BinaryReader reader)
         {
         {
             long word0 = reader.ReadUInt32();
             long word0 = reader.ReadUInt32();
@@ -22,5 +29,25 @@ namespace Ryujinx.HLE.HOS.Ipc
 
 
             Size = (ushort)(word0 >> 16);
             Size = (ushort)(word0 >> 16);
         }
         }
+
+        public uint GetWord0()
+        {
+            uint word0;
+
+            word0  = (uint)((Position & 0x0f00000000) >> 20);
+            word0 |= (uint)((Position & 0x7000000000) >> 30);
+
+            word0 |= (uint)(Index & 0x03f) << 0;
+            word0 |= (uint)(Index & 0x1c0) << 3;
+
+            word0 |= (uint)Size << 16;
+
+            return word0;
+        }
+
+        public uint GetWord1()
+        {
+            return (uint)Position;
+        }
     }
     }
 }
 }

+ 6 - 0
Ryujinx.HLE/HOS/Ipc/IpcRecvListBuffDesc.cs

@@ -7,6 +7,12 @@ namespace Ryujinx.HLE.HOS.Ipc
         public long Position { get; private set; }
         public long Position { get; private set; }
         public long Size     { get; private set; }
         public long Size     { get; private set; }
 
 
+        public IpcRecvListBuffDesc(long position, long size)
+        {
+            Position = position;
+            Size = size;
+        }
+
         public IpcRecvListBuffDesc(BinaryReader reader)
         public IpcRecvListBuffDesc(BinaryReader reader)
         {
         {
             long value = reader.ReadInt64();
             long value = reader.ReadInt64();

+ 11 - 0
Ryujinx.HLE/HOS/Kernel/Common/OnScopeExit.cs

@@ -0,0 +1,11 @@
+using System;
+
+namespace Ryujinx.HLE.HOS.Kernel.Common
+{
+    struct OnScopeExit : IDisposable
+    {
+        private readonly Action _action;
+        public OnScopeExit(Action action) => _action = action;
+        public void Dispose() => _action();
+    }
+}

+ 2 - 2
Ryujinx.HLE/HOS/Kernel/Ipc/KBufferDescriptorTable.cs

@@ -99,7 +99,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
                         copySize,
                         copySize,
                         stateMask,
                         stateMask,
                         stateMask,
                         stateMask,
-                        MemoryPermission.ReadAndWrite,
+                        KMemoryPermission.ReadAndWrite,
                         attributeMask,
                         attributeMask,
                         MemoryAttribute.None,
                         MemoryAttribute.None,
                         desc.ServerAddress);
                         desc.ServerAddress);
@@ -125,7 +125,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
                         clientEndAddr - clientEndAddrTruncated,
                         clientEndAddr - clientEndAddrTruncated,
                         stateMask,
                         stateMask,
                         stateMask,
                         stateMask,
-                        MemoryPermission.ReadAndWrite,
+                        KMemoryPermission.ReadAndWrite,
                         attributeMask,
                         attributeMask,
                         MemoryAttribute.None,
                         MemoryAttribute.None,
                         serverEndAddrTruncated);
                         serverEndAddrTruncated);

+ 0 - 9
Ryujinx.HLE/HOS/Kernel/Ipc/KClientPort.cs

@@ -14,10 +14,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
 
 
         public bool IsLight => _parent.IsLight;
         public bool IsLight => _parent.IsLight;
 
 
-        // 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(KernelContext context, KPort parent, int maxSessions) : base(context)
         public KClientPort(KernelContext context, KPort parent, int maxSessions) : base(context)
         {
         {
             _maxSessions = maxSessions;
             _maxSessions = maxSessions;
@@ -45,11 +41,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
 
 
             KSession session = new KSession(KernelContext, this);
             KSession session = new KSession(KernelContext, this);
 
 
-            if (Service != null)
-            {
-                session.ClientSession.Service = Service;
-            }
-
             KernelResult result = _parent.EnqueueIncomingSession(session.ServerSession);
             KernelResult result = _parent.EnqueueIncomingSession(session.ServerSession);
 
 
             if (result != KernelResult.Success)
             if (result != KernelResult.Success)

+ 0 - 9
Ryujinx.HLE/HOS/Kernel/Ipc/KClientSession.cs

@@ -16,10 +16,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
 
 
         public KClientPort ParentPort { get; }
         public KClientPort ParentPort { get; }
 
 
-        // TODO: Remove that, we need it for now to allow HLE
-        // services implementation to work with the new IPC system.
-        public IpcService Service { get; set; }
-
         public KClientSession(KernelContext context, KSession parent, KClientPort parentPort) : base(context)
         public KClientSession(KernelContext context, KSession parent, KClientPort parentPort) : base(context)
         {
         {
             _parent    = parent;
             _parent    = parent;
@@ -84,11 +80,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
         {
         {
             _parent.DisconnectClient();
             _parent.DisconnectClient();
             _parent.DecrementReferenceCount();
             _parent.DecrementReferenceCount();
-
-            if (Service is IDisposable disposableObj)
-            {
-                disposableObj.Dispose();
-            }
         }
         }
     }
     }
 }
 }

+ 13 - 21
Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs

@@ -430,7 +430,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
                         descriptor.BufferAddress,
                         descriptor.BufferAddress,
                         MemoryState.IsPoolAllocated,
                         MemoryState.IsPoolAllocated,
                         MemoryState.IsPoolAllocated,
                         MemoryState.IsPoolAllocated,
-                        MemoryPermission.Read,
+                        KMemoryPermission.Read,
                         MemoryAttribute.Uncached,
                         MemoryAttribute.Uncached,
                         MemoryAttribute.None);
                         MemoryAttribute.None);
 
 
@@ -473,9 +473,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
                 bool notReceiveDesc = isSendDesc || isExchangeDesc;
                 bool notReceiveDesc = isSendDesc || isExchangeDesc;
                 bool isReceiveDesc  = !notReceiveDesc;
                 bool isReceiveDesc  = !notReceiveDesc;
 
 
-                MemoryPermission permission = index >= clientHeader.SendBuffersCount
-                    ? MemoryPermission.ReadAndWrite
-                    : MemoryPermission.Read;
+                KMemoryPermission permission = index >= clientHeader.SendBuffersCount
+                    ? KMemoryPermission.ReadAndWrite
+                    : KMemoryPermission.Read;
 
 
                 uint sizeHigh4 = (descWord2 >> 24) & 0xf;
                 uint sizeHigh4 = (descWord2 >> 24) & 0xf;
 
 
@@ -559,9 +559,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
 
 
                 if (serverMsg.IsCustom || clientMsg.IsCustom)
                 if (serverMsg.IsCustom || clientMsg.IsCustom)
                 {
                 {
-                    MemoryPermission permission = clientMsg.IsCustom
-                        ? MemoryPermission.None
-                        : MemoryPermission.Read;
+                    KMemoryPermission permission = clientMsg.IsCustom
+                        ? KMemoryPermission.None
+                        : KMemoryPermission.Read;
 
 
                     clientResult = clientProcess.MemoryManager.CopyDataToCurrentProcess(
                     clientResult = clientProcess.MemoryManager.CopyDataToCurrentProcess(
                         copyDst,
                         copyDst,
@@ -795,7 +795,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
                         descriptor.BufferSize,
                         descriptor.BufferSize,
                         MemoryState.IsPoolAllocated,
                         MemoryState.IsPoolAllocated,
                         MemoryState.IsPoolAllocated,
                         MemoryState.IsPoolAllocated,
-                        MemoryPermission.Read,
+                        KMemoryPermission.Read,
                         MemoryAttribute.Uncached,
                         MemoryAttribute.Uncached,
                         MemoryAttribute.None,
                         MemoryAttribute.None,
                         descriptor.BufferAddress);
                         descriptor.BufferAddress);
@@ -849,9 +849,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
 
 
                 if (serverMsg.IsCustom || clientMsg.IsCustom)
                 if (serverMsg.IsCustom || clientMsg.IsCustom)
                 {
                 {
-                    MemoryPermission permission = clientMsg.IsCustom
-                        ? MemoryPermission.None
-                        : MemoryPermission.Read;
+                    KMemoryPermission permission = clientMsg.IsCustom
+                        ? KMemoryPermission.None
+                        : KMemoryPermission.Read;
 
 
                     clientResult = clientProcess.MemoryManager.CopyDataFromCurrentProcess(
                     clientResult = clientProcess.MemoryManager.CopyDataFromCurrentProcess(
                         copyDst,
                         copyDst,
@@ -898,11 +898,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
             return new MessageHeader(word0, word1, word2);
             return new MessageHeader(word0, word1, word2);
         }
         }
 
 
-        private KernelResult GetCopyObjectHandle(
-            KThread  srcThread,
-            KProcess dstProcess,
-            int      srcHandle,
-            out int  dstHandle)
+        private KernelResult GetCopyObjectHandle(KThread srcThread, KProcess dstProcess, int srcHandle, out int dstHandle)
         {
         {
             dstHandle = 0;
             dstHandle = 0;
 
 
@@ -933,11 +929,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
             }
             }
         }
         }
 
 
-        private KernelResult GetMoveObjectHandle(
-            KProcess srcProcess,
-            KProcess dstProcess,
-            int      srcHandle,
-            out int  dstHandle)
+        private KernelResult GetMoveObjectHandle(KProcess srcProcess, KProcess dstProcess, int srcHandle, out int dstHandle)
         {
         {
             dstHandle = 0;
             dstHandle = 0;
 
 

+ 1 - 14
Ryujinx.HLE/HOS/Kernel/Ipc/KSession.cs

@@ -4,7 +4,7 @@ using System;
 
 
 namespace Ryujinx.HLE.HOS.Kernel.Ipc
 namespace Ryujinx.HLE.HOS.Kernel.Ipc
 {
 {
-    class KSession : KAutoObject, IDisposable
+    class KSession : KAutoObject
     {
     {
         public KServerSession ServerSession { get; }
         public KServerSession ServerSession { get; }
         public KClientSession ClientSession { get; }
         public KClientSession ClientSession { get; }
@@ -37,19 +37,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
             }
             }
         }
         }
 
 
-        public void Dispose()
-        {
-            Dispose(true);
-        }
-
-        protected virtual void Dispose(bool disposing)
-        {
-            if (disposing && ClientSession.Service is IDisposable disposableService)
-            {
-                disposableService.Dispose();
-            }
-        }
-
         protected override void Destroy()
         protected override void Destroy()
         {
         {
             if (_hasBeenInitialized)
             if (_hasBeenInitialized)

+ 1 - 1
Ryujinx.HLE/HOS/Kernel/KernelContext.cs

@@ -51,7 +51,7 @@ namespace Ryujinx.HLE.HOS.Kernel
             Device = device;
             Device = device;
             Memory = memory;
             Memory = memory;
 
 
-            Syscall = new Syscall(device, this);
+            Syscall = new Syscall(this);
 
 
             SyscallHandler = new SyscallHandler(this);
             SyscallHandler = new SyscallHandler(this);
 
 

+ 38 - 0
Ryujinx.HLE/HOS/Kernel/KernelStatic.cs

@@ -0,0 +1,38 @@
+using Ryujinx.HLE.HOS.Kernel.Threading;
+using System;
+using System.Threading.Tasks;
+
+namespace Ryujinx.HLE.HOS.Kernel
+{
+    static class KernelStatic
+    {
+        [ThreadStatic]
+        private static KernelContext Context;
+
+        public static void YieldUntilCompletion(Action action)
+        {
+            YieldUntilCompletion(Task.Factory.StartNew(action));
+        }
+
+        public static void YieldUntilCompletion(Task task)
+        {
+            KThread currentThread = Context.Scheduler.GetCurrentThread();
+
+            Context.CriticalSection.Enter();
+
+            currentThread.Reschedule(ThreadSchedState.Paused);
+
+            task.ContinueWith((antecedent) =>
+            {
+                currentThread.Reschedule(ThreadSchedState.Running);
+            });
+
+            Context.CriticalSection.Leave();
+        }
+
+        internal static void SetKernelContext(KernelContext context)
+        {
+            Context = context;
+        }
+    }
+}

+ 8 - 8
Ryujinx.HLE/HOS/Kernel/Memory/KMemoryBlock.cs

@@ -8,9 +8,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
         public ulong PagesCount  { get; private set; }
         public ulong PagesCount  { get; private set; }
 
 
         public MemoryState      State            { get; private set; }
         public MemoryState      State            { get; private set; }
-        public MemoryPermission Permission       { get; private set; }
+        public KMemoryPermission Permission       { get; private set; }
         public MemoryAttribute  Attribute        { get; private set; }
         public MemoryAttribute  Attribute        { get; private set; }
-        public MemoryPermission SourcePermission { get; private set; }
+        public KMemoryPermission SourcePermission { get; private set; }
 
 
         public int IpcRefCount    { get; private set; }
         public int IpcRefCount    { get; private set; }
         public int DeviceRefCount { get; private set; }
         public int DeviceRefCount { get; private set; }
@@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong            baseAddress,
             ulong            baseAddress,
             ulong            pagesCount,
             ulong            pagesCount,
             MemoryState      state,
             MemoryState      state,
-            MemoryPermission permission,
+            KMemoryPermission permission,
             MemoryAttribute  attribute,
             MemoryAttribute  attribute,
             int              ipcRefCount    = 0,
             int              ipcRefCount    = 0,
             int              deviceRefCount = 0)
             int              deviceRefCount = 0)
@@ -33,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             DeviceRefCount = deviceRefCount;
             DeviceRefCount = deviceRefCount;
         }
         }
 
 
-        public void SetState(MemoryPermission permission, MemoryState state, MemoryAttribute attribute)
+        public void SetState(KMemoryPermission permission, MemoryState state, MemoryAttribute attribute)
         {
         {
             Permission = permission;
             Permission = permission;
             State      = state;
             State      = state;
@@ -41,7 +41,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             Attribute |= attribute;
             Attribute |= attribute;
         }
         }
 
 
-        public void SetIpcMappingPermission(MemoryPermission newPermission)
+        public void SetIpcMappingPermission(KMemoryPermission newPermission)
         {
         {
             int oldIpcRefCount = IpcRefCount++;
             int oldIpcRefCount = IpcRefCount++;
 
 
@@ -54,8 +54,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             {
             {
                 SourcePermission = Permission;
                 SourcePermission = Permission;
 
 
-                Permission &= ~MemoryPermission.ReadAndWrite;
-                Permission |=  MemoryPermission.ReadAndWrite & newPermission;
+                Permission &= ~KMemoryPermission.ReadAndWrite;
+                Permission |=  KMemoryPermission.ReadAndWrite & newPermission;
             }
             }
 
 
             Attribute |= MemoryAttribute.IpcMapped;
             Attribute |= MemoryAttribute.IpcMapped;
@@ -74,7 +74,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             {
             {
                 Permission = SourcePermission;
                 Permission = SourcePermission;
 
 
-                SourcePermission = MemoryPermission.None;
+                SourcePermission = KMemoryPermission.None;
 
 
                 Attribute &= ~MemoryAttribute.IpcMapped;
                 Attribute &= ~MemoryAttribute.IpcMapped;
             }
             }

+ 4 - 4
Ryujinx.HLE/HOS/Kernel/Memory/KMemoryInfo.cs

@@ -6,9 +6,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
         public ulong Size    { get; }
         public ulong Size    { get; }
 
 
         public MemoryState      State            { get; }
         public MemoryState      State            { get; }
-        public MemoryPermission Permission       { get; }
+        public KMemoryPermission Permission       { get; }
         public MemoryAttribute  Attribute        { get; }
         public MemoryAttribute  Attribute        { get; }
-        public MemoryPermission SourcePermission { get; }
+        public KMemoryPermission SourcePermission { get; }
 
 
         public int IpcRefCount    { get; }
         public int IpcRefCount    { get; }
         public int DeviceRefCount { get; }
         public int DeviceRefCount { get; }
@@ -17,9 +17,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong            address,
             ulong            address,
             ulong            size,
             ulong            size,
             MemoryState      state,
             MemoryState      state,
-            MemoryPermission permission,
+            KMemoryPermission permission,
             MemoryAttribute  attribute,
             MemoryAttribute  attribute,
-            MemoryPermission sourcePermission,
+            KMemoryPermission sourcePermission,
             int              ipcRefCount,
             int              ipcRefCount,
             int              deviceRefCount)
             int              deviceRefCount)
         {
         {

+ 176 - 151
Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs

@@ -1,9 +1,10 @@
 using Ryujinx.Common;
 using Ryujinx.Common;
-using Ryujinx.Cpu;
 using Ryujinx.HLE.HOS.Kernel.Common;
 using Ryujinx.HLE.HOS.Kernel.Common;
 using Ryujinx.HLE.HOS.Kernel.Process;
 using Ryujinx.HLE.HOS.Kernel.Process;
+using Ryujinx.Memory;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.Diagnostics;
 
 
 namespace Ryujinx.HLE.HOS.Kernel.Memory
 namespace Ryujinx.HLE.HOS.Kernel.Memory
 {
 {
@@ -27,11 +28,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
         // needs to be split in 2, plus one block that will be the new one inserted.
         // needs to be split in 2, plus one block that will be the new one inserted.
         private const int MaxBlocksNeededForInsertion = 2;
         private const int MaxBlocksNeededForInsertion = 2;
 
 
-        private LinkedList<KMemoryBlock> _blocks;
+        private readonly LinkedList<KMemoryBlock> _blocks;
 
 
-        private MemoryManager _cpuMemory;
+        private readonly IVirtualMemoryManager _cpuMemory;
 
 
-        private KernelContext _context;
+        private readonly KernelContext _context;
 
 
         public ulong AddrSpaceStart { get; private set; }
         public ulong AddrSpaceStart { get; private set; }
         public ulong AddrSpaceEnd   { get; private set; }
         public ulong AddrSpaceEnd   { get; private set; }
@@ -73,7 +74,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
 
 
         private MersenneTwister _randomNumberGenerator;
         private MersenneTwister _randomNumberGenerator;
 
 
-        public KMemoryManager(KernelContext context, MemoryManager cpuMemory)
+        public KMemoryManager(KernelContext context, IVirtualMemoryManager cpuMemory)
         {
         {
             _context   = context;
             _context   = context;
             _cpuMemory = cpuMemory;
             _cpuMemory = cpuMemory;
@@ -352,7 +353,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                 addrSpaceStart,
                 addrSpaceStart,
                 addrSpacePagesCount,
                 addrSpacePagesCount,
                 MemoryState.Unmapped,
                 MemoryState.Unmapped,
-                MemoryPermission.None,
+                KMemoryPermission.None,
                 MemoryAttribute.None));
                 MemoryAttribute.None));
 
 
             return KernelResult.Success;
             return KernelResult.Success;
@@ -362,13 +363,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong            address,
             ulong            address,
             KPageList        pageList,
             KPageList        pageList,
             MemoryState      state,
             MemoryState      state,
-            MemoryPermission permission)
+            KMemoryPermission permission)
         {
         {
             ulong pagesCount = pageList.GetPagesCount();
             ulong pagesCount = pageList.GetPagesCount();
 
 
             ulong size = pagesCount * PageSize;
             ulong size = pagesCount * PageSize;
 
 
-            if (!ValidateRegionForState(address, size, state))
+            if (!CanContain(address, size, state))
             {
             {
                 return KernelResult.InvalidMemState;
                 return KernelResult.InvalidMemState;
             }
             }
@@ -437,8 +438,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     size,
                     size,
                     MemoryState.Mask,
                     MemoryState.Mask,
                     stateExpected,
                     stateExpected,
-                    MemoryPermission.None,
-                    MemoryPermission.None,
+                    KMemoryPermission.None,
+                    KMemoryPermission.None,
                     MemoryAttribute.Mask,
                     MemoryAttribute.Mask,
                     MemoryAttribute.None,
                     MemoryAttribute.None,
                     MemoryAttribute.IpcAndDeviceMapped,
                     MemoryAttribute.IpcAndDeviceMapped,
@@ -467,13 +468,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             }
             }
         }
         }
 
 
-        public KernelResult MapNormalMemory(long address, long size, MemoryPermission permission)
+        public KernelResult MapNormalMemory(long address, long size, KMemoryPermission permission)
         {
         {
             // TODO.
             // TODO.
             return KernelResult.Success;
             return KernelResult.Success;
         }
         }
 
 
-        public KernelResult MapIoMemory(long address, long size, MemoryPermission permission)
+        public KernelResult MapIoMemory(long address, long size, KMemoryPermission permission)
         {
         {
             // TODO.
             // TODO.
             return KernelResult.Success;
             return KernelResult.Success;
@@ -487,7 +488,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong            regionStart,
             ulong            regionStart,
             ulong            regionPagesCount,
             ulong            regionPagesCount,
             MemoryState      state,
             MemoryState      state,
-            MemoryPermission permission,
+            KMemoryPermission permission,
             out ulong        address)
             out ulong        address)
         {
         {
             address = 0;
             address = 0;
@@ -496,7 +497,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
 
 
             ulong regionEndAddr = regionStart + regionSize;
             ulong regionEndAddr = regionStart + regionSize;
 
 
-            if (!ValidateRegionForState(regionStart, regionSize, state))
+            if (!CanContain(regionStart, regionSize, state))
             {
             {
                 return KernelResult.InvalidMemState;
                 return KernelResult.InvalidMemState;
             }
             }
@@ -547,11 +548,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong            address,
             ulong            address,
             ulong            pagesCount,
             ulong            pagesCount,
             MemoryState      state,
             MemoryState      state,
-            MemoryPermission permission)
+            KMemoryPermission permission)
         {
         {
             ulong size = pagesCount * PageSize;
             ulong size = pagesCount * PageSize;
 
 
-            if (!ValidateRegionForState(address, size, state))
+            if (!CanContain(address, size, state))
             {
             {
                 return KernelResult.InvalidMemState;
                 return KernelResult.InvalidMemState;
             }
             }
@@ -596,13 +597,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     size,
                     size,
                     MemoryState.Mask,
                     MemoryState.Mask,
                     MemoryState.Heap,
                     MemoryState.Heap,
-                    MemoryPermission.Mask,
-                    MemoryPermission.ReadAndWrite,
+                    KMemoryPermission.Mask,
+                    KMemoryPermission.ReadAndWrite,
                     MemoryAttribute.Mask,
                     MemoryAttribute.Mask,
                     MemoryAttribute.None,
                     MemoryAttribute.None,
                     MemoryAttribute.IpcAndDeviceMapped,
                     MemoryAttribute.IpcAndDeviceMapped,
                     out MemoryState      state,
                     out MemoryState      state,
-                    out MemoryPermission permission,
+                    out KMemoryPermission permission,
                     out _);
                     out _);
 
 
                 success &= IsUnmapped(dst, size);
                 success &= IsUnmapped(dst, size);
@@ -618,14 +619,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
 
 
                     AddVaRangeToPageList(pageList, src, pagesCount);
                     AddVaRangeToPageList(pageList, src, pagesCount);
 
 
-                    KernelResult result = MmuChangePermission(src, pagesCount, MemoryPermission.None);
+                    KernelResult result = MmuChangePermission(src, pagesCount, KMemoryPermission.None);
 
 
                     if (result != KernelResult.Success)
                     if (result != KernelResult.Success)
                     {
                     {
                         return result;
                         return result;
                     }
                     }
 
 
-                    result = MapPages(dst, pageList, MemoryPermission.None);
+                    result = MapPages(dst, pageList, KMemoryPermission.None);
 
 
                     if (result != KernelResult.Success)
                     if (result != KernelResult.Success)
                     {
                     {
@@ -634,7 +635,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                         return result;
                         return result;
                     }
                     }
 
 
-                    InsertBlock(src, pagesCount, state, MemoryPermission.None, MemoryAttribute.Borrowed);
+                    InsertBlock(src, pagesCount, state, KMemoryPermission.None, MemoryAttribute.Borrowed);
                     InsertBlock(dst, pagesCount, MemoryState.ModCodeStatic);
                     InsertBlock(dst, pagesCount, MemoryState.ModCodeStatic);
 
 
                     return KernelResult.Success;
                     return KernelResult.Success;
@@ -657,8 +658,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     size,
                     size,
                     MemoryState.Mask,
                     MemoryState.Mask,
                     MemoryState.Heap,
                     MemoryState.Heap,
-                    MemoryPermission.None,
-                    MemoryPermission.None,
+                    KMemoryPermission.None,
+                    KMemoryPermission.None,
                     MemoryAttribute.Mask,
                     MemoryAttribute.Mask,
                     MemoryAttribute.Borrowed,
                     MemoryAttribute.Borrowed,
                     MemoryAttribute.IpcAndDeviceMapped,
                     MemoryAttribute.IpcAndDeviceMapped,
@@ -671,8 +672,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     PageSize,
                     PageSize,
                     MemoryState.UnmapProcessCodeMemoryAllowed,
                     MemoryState.UnmapProcessCodeMemoryAllowed,
                     MemoryState.UnmapProcessCodeMemoryAllowed,
                     MemoryState.UnmapProcessCodeMemoryAllowed,
-                    MemoryPermission.None,
-                    MemoryPermission.None,
+                    KMemoryPermission.None,
+                    KMemoryPermission.None,
                     MemoryAttribute.Mask,
                     MemoryAttribute.Mask,
                     MemoryAttribute.None,
                     MemoryAttribute.None,
                     MemoryAttribute.IpcAndDeviceMapped,
                     MemoryAttribute.IpcAndDeviceMapped,
@@ -685,8 +686,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     size,
                     size,
                     MemoryState.Mask,
                     MemoryState.Mask,
                     state,
                     state,
-                    MemoryPermission.None,
-                    MemoryPermission.None,
+                    KMemoryPermission.None,
+                    KMemoryPermission.None,
                     MemoryAttribute.Mask,
                     MemoryAttribute.Mask,
                     MemoryAttribute.None);
                     MemoryAttribute.None);
 
 
@@ -707,7 +708,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     }
                     }
 
 
                     InsertBlock(dst, pagesCount, MemoryState.Unmapped);
                     InsertBlock(dst, pagesCount, MemoryState.Unmapped);
-                    InsertBlock(src, pagesCount, MemoryState.Heap, MemoryPermission.ReadAndWrite);
+                    InsertBlock(src, pagesCount, MemoryState.Heap, KMemoryPermission.ReadAndWrite);
 
 
                     return KernelResult.Success;
                     return KernelResult.Success;
                 }
                 }
@@ -788,7 +789,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                         _currentHeapAddr,
                         _currentHeapAddr,
                         pagesCount,
                         pagesCount,
                         pageList,
                         pageList,
-                        MemoryPermission.ReadAndWrite,
+                        KMemoryPermission.ReadAndWrite,
                         MemoryOperation.MapVa);
                         MemoryOperation.MapVa);
 
 
                     if (result != KernelResult.Success)
                     if (result != KernelResult.Success)
@@ -798,7 +799,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                         return result;
                         return result;
                     }
                     }
 
 
-                    InsertBlock(_currentHeapAddr, pagesCount, MemoryState.Heap, MemoryPermission.ReadAndWrite);
+                    InsertBlock(_currentHeapAddr, pagesCount, MemoryState.Heap, KMemoryPermission.ReadAndWrite);
                 }
                 }
                 else
                 else
                 {
                 {
@@ -816,8 +817,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                         sizeDelta,
                         sizeDelta,
                         MemoryState.Mask,
                         MemoryState.Mask,
                         MemoryState.Heap,
                         MemoryState.Heap,
-                        MemoryPermission.Mask,
-                        MemoryPermission.ReadAndWrite,
+                        KMemoryPermission.Mask,
+                        KMemoryPermission.ReadAndWrite,
                         MemoryAttribute.Mask,
                         MemoryAttribute.Mask,
                         MemoryAttribute.None,
                         MemoryAttribute.None,
                         MemoryAttribute.IpcAndDeviceMapped,
                         MemoryAttribute.IpcAndDeviceMapped,
@@ -886,13 +887,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     size,
                     size,
                     MemoryState.AttributeChangeAllowed,
                     MemoryState.AttributeChangeAllowed,
                     MemoryState.AttributeChangeAllowed,
                     MemoryState.AttributeChangeAllowed,
-                    MemoryPermission.None,
-                    MemoryPermission.None,
+                    KMemoryPermission.None,
+                    KMemoryPermission.None,
                     MemoryAttribute.BorrowedAndIpcMapped,
                     MemoryAttribute.BorrowedAndIpcMapped,
                     MemoryAttribute.None,
                     MemoryAttribute.None,
                     MemoryAttribute.DeviceMappedAndUncached,
                     MemoryAttribute.DeviceMappedAndUncached,
                     out MemoryState      state,
                     out MemoryState      state,
-                    out MemoryPermission permission,
+                    out KMemoryPermission permission,
                     out MemoryAttribute  attribute))
                     out MemoryAttribute  attribute))
                 {
                 {
                     if (!_blockAllocator.CanAllocate(MaxBlocksNeededForInsertion))
                     if (!_blockAllocator.CanAllocate(MaxBlocksNeededForInsertion))
@@ -932,9 +933,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     AddrSpaceEnd,
                     AddrSpaceEnd,
                     ~AddrSpaceEnd + 1,
                     ~AddrSpaceEnd + 1,
                     MemoryState.Reserved,
                     MemoryState.Reserved,
-                    MemoryPermission.None,
+                    KMemoryPermission.None,
                     MemoryAttribute.None,
                     MemoryAttribute.None,
-                    MemoryPermission.None,
+                    KMemoryPermission.None,
                     0,
                     0,
                     0);
                     0);
             }
             }
@@ -951,8 +952,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     size,
                     size,
                     MemoryState.MapAllowed,
                     MemoryState.MapAllowed,
                     MemoryState.MapAllowed,
                     MemoryState.MapAllowed,
-                    MemoryPermission.Mask,
-                    MemoryPermission.ReadAndWrite,
+                    KMemoryPermission.Mask,
+                    KMemoryPermission.ReadAndWrite,
                     MemoryAttribute.Mask,
                     MemoryAttribute.Mask,
                     MemoryAttribute.None,
                     MemoryAttribute.None,
                     MemoryAttribute.IpcAndDeviceMapped,
                     MemoryAttribute.IpcAndDeviceMapped,
@@ -975,18 +976,18 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
 
 
                     AddVaRangeToPageList(pageList, src, pagesCount);
                     AddVaRangeToPageList(pageList, src, pagesCount);
 
 
-                    KernelResult result = MmuChangePermission(src, pagesCount, MemoryPermission.None);
+                    KernelResult result = MmuChangePermission(src, pagesCount, KMemoryPermission.None);
 
 
                     if (result != KernelResult.Success)
                     if (result != KernelResult.Success)
                     {
                     {
                         return result;
                         return result;
                     }
                     }
 
 
-                    result = MapPages(dst, pageList, MemoryPermission.ReadAndWrite);
+                    result = MapPages(dst, pageList, KMemoryPermission.ReadAndWrite);
 
 
                     if (result != KernelResult.Success)
                     if (result != KernelResult.Success)
                     {
                     {
-                        if (MmuChangePermission(src, pagesCount, MemoryPermission.ReadAndWrite) != KernelResult.Success)
+                        if (MmuChangePermission(src, pagesCount, KMemoryPermission.ReadAndWrite) != KernelResult.Success)
                         {
                         {
                             throw new InvalidOperationException("Unexpected failure reverting memory permission.");
                             throw new InvalidOperationException("Unexpected failure reverting memory permission.");
                         }
                         }
@@ -994,8 +995,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                         return result;
                         return result;
                     }
                     }
 
 
-                    InsertBlock(src, pagesCount, srcState, MemoryPermission.None, MemoryAttribute.Borrowed);
-                    InsertBlock(dst, pagesCount, MemoryState.Stack, MemoryPermission.ReadAndWrite);
+                    InsertBlock(src, pagesCount, srcState, KMemoryPermission.None, MemoryAttribute.Borrowed);
+                    InsertBlock(dst, pagesCount, MemoryState.Stack, KMemoryPermission.ReadAndWrite);
 
 
                     return KernelResult.Success;
                     return KernelResult.Success;
                 }
                 }
@@ -1017,8 +1018,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     size,
                     size,
                     MemoryState.Mask,
                     MemoryState.Mask,
                     stateExpected,
                     stateExpected,
-                    MemoryPermission.None,
-                    MemoryPermission.None,
+                    KMemoryPermission.None,
+                    KMemoryPermission.None,
                     MemoryAttribute.Mask,
                     MemoryAttribute.Mask,
                     MemoryAttribute.None,
                     MemoryAttribute.None,
                     MemoryAttribute.IpcAndDeviceMapped,
                     MemoryAttribute.IpcAndDeviceMapped,
@@ -1058,8 +1059,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     size,
                     size,
                     MemoryState.MapAllowed,
                     MemoryState.MapAllowed,
                     MemoryState.MapAllowed,
                     MemoryState.MapAllowed,
-                    MemoryPermission.Mask,
-                    MemoryPermission.None,
+                    KMemoryPermission.Mask,
+                    KMemoryPermission.None,
                     MemoryAttribute.Mask,
                     MemoryAttribute.Mask,
                     MemoryAttribute.Borrowed,
                     MemoryAttribute.Borrowed,
                     MemoryAttribute.IpcAndDeviceMapped,
                     MemoryAttribute.IpcAndDeviceMapped,
@@ -1072,13 +1073,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     size,
                     size,
                     MemoryState.Mask,
                     MemoryState.Mask,
                     MemoryState.Stack,
                     MemoryState.Stack,
-                    MemoryPermission.None,
-                    MemoryPermission.None,
+                    KMemoryPermission.None,
+                    KMemoryPermission.None,
                     MemoryAttribute.Mask,
                     MemoryAttribute.Mask,
                     MemoryAttribute.None,
                     MemoryAttribute.None,
                     MemoryAttribute.IpcAndDeviceMapped,
                     MemoryAttribute.IpcAndDeviceMapped,
                     out _,
                     out _,
-                    out MemoryPermission dstPermission,
+                    out KMemoryPermission dstPermission,
                     out _);
                     out _);
 
 
                 if (success)
                 if (success)
@@ -1108,7 +1109,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                         return result;
                         return result;
                     }
                     }
 
 
-                    result = MmuChangePermission(src, pagesCount, MemoryPermission.ReadAndWrite);
+                    result = MmuChangePermission(src, pagesCount, KMemoryPermission.ReadAndWrite);
 
 
                     if (result != KernelResult.Success)
                     if (result != KernelResult.Success)
                     {
                     {
@@ -1117,7 +1118,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                         return result;
                         return result;
                     }
                     }
 
 
-                    InsertBlock(src, pagesCount, srcState, MemoryPermission.ReadAndWrite);
+                    InsertBlock(src, pagesCount, srcState, KMemoryPermission.ReadAndWrite);
                     InsertBlock(dst, pagesCount, MemoryState.Unmapped);
                     InsertBlock(dst, pagesCount, MemoryState.Unmapped);
 
 
                     return KernelResult.Success;
                     return KernelResult.Success;
@@ -1129,7 +1130,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             }
             }
         }
         }
 
 
-        public KernelResult SetProcessMemoryPermission(ulong address, ulong size, MemoryPermission permission)
+        public KernelResult SetProcessMemoryPermission(ulong address, ulong size, KMemoryPermission permission)
         {
         {
             lock (_blocks)
             lock (_blocks)
             {
             {
@@ -1138,20 +1139,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     size,
                     size,
                     MemoryState.ProcessPermissionChangeAllowed,
                     MemoryState.ProcessPermissionChangeAllowed,
                     MemoryState.ProcessPermissionChangeAllowed,
                     MemoryState.ProcessPermissionChangeAllowed,
-                    MemoryPermission.None,
-                    MemoryPermission.None,
+                    KMemoryPermission.None,
+                    KMemoryPermission.None,
                     MemoryAttribute.Mask,
                     MemoryAttribute.Mask,
                     MemoryAttribute.None,
                     MemoryAttribute.None,
                     MemoryAttribute.IpcAndDeviceMapped,
                     MemoryAttribute.IpcAndDeviceMapped,
                     out MemoryState      oldState,
                     out MemoryState      oldState,
-                    out MemoryPermission oldPermission,
+                    out KMemoryPermission oldPermission,
                     out _))
                     out _))
                 {
                 {
                     MemoryState newState = oldState;
                     MemoryState newState = oldState;
 
 
                     // If writing into the code region is allowed, then we need
                     // If writing into the code region is allowed, then we need
                     // to change it to mutable.
                     // to change it to mutable.
-                    if ((permission & MemoryPermission.Write) != 0)
+                    if ((permission & KMemoryPermission.Write) != 0)
                     {
                     {
                         if (oldState == MemoryState.CodeStatic)
                         if (oldState == MemoryState.CodeStatic)
                         {
                         {
@@ -1176,7 +1177,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
 
 
                         ulong pagesCount = size / PageSize;
                         ulong pagesCount = size / PageSize;
 
 
-                        MemoryOperation operation = (permission & MemoryPermission.Execute) != 0
+                        MemoryOperation operation = (permission & KMemoryPermission.Execute) != 0
                             ? MemoryOperation.ChangePermsAndAttributes
                             ? MemoryOperation.ChangePermsAndAttributes
                             : MemoryOperation.ChangePermRw;
                             : MemoryOperation.ChangePermRw;
 
 
@@ -1270,10 +1271,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     address,
                     address,
                     pagesCount,
                     pagesCount,
                     MemoryState.Unmapped,
                     MemoryState.Unmapped,
-                    MemoryPermission.None,
+                    KMemoryPermission.None,
                     MemoryAttribute.None,
                     MemoryAttribute.None,
                     MemoryState.Heap,
                     MemoryState.Heap,
-                    MemoryPermission.ReadAndWrite,
+                    KMemoryPermission.ReadAndWrite,
                     MemoryAttribute.None);
                     MemoryAttribute.None);
             }
             }
 
 
@@ -1410,7 +1411,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                             pagesCount,
                             pagesCount,
                             srcPa,
                             srcPa,
                             true,
                             true,
-                            MemoryPermission.ReadAndWrite,
+                            KMemoryPermission.ReadAndWrite,
                             MemoryOperation.MapPa);
                             MemoryOperation.MapPa);
 
 
                         dstVa      += pagesCount * PageSize;
                         dstVa      += pagesCount * PageSize;
@@ -1428,7 +1429,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong            src,
             ulong            src,
             MemoryState      stateMask,
             MemoryState      stateMask,
             MemoryState      stateExpected,
             MemoryState      stateExpected,
-            MemoryPermission permission,
+            KMemoryPermission permission,
             MemoryAttribute  attributeMask,
             MemoryAttribute  attributeMask,
             MemoryAttribute  attributeExpected)
             MemoryAttribute  attributeExpected)
         {
         {
@@ -1450,7 +1451,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong            size,
             ulong            size,
             MemoryState      stateMask,
             MemoryState      stateMask,
             MemoryState      stateExpected,
             MemoryState      stateExpected,
-            MemoryPermission permission,
+            KMemoryPermission permission,
             MemoryAttribute  attributeMask,
             MemoryAttribute  attributeMask,
             MemoryAttribute  attributeExpected,
             MemoryAttribute  attributeExpected,
             ulong            src)
             ulong            src)
@@ -1474,7 +1475,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong            serverAddress,
             ulong            serverAddress,
             MemoryState      stateMask,
             MemoryState      stateMask,
             MemoryState      stateExpected,
             MemoryState      stateExpected,
-            MemoryPermission permission,
+            KMemoryPermission permission,
             MemoryAttribute  attributeMask,
             MemoryAttribute  attributeMask,
             MemoryAttribute  attributeExpected,
             MemoryAttribute  attributeExpected,
             bool             toServer)
             bool             toServer)
@@ -1529,7 +1530,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong            size,
             ulong            size,
             ulong            src,
             ulong            src,
             KMemoryManager   sourceMemMgr,
             KMemoryManager   sourceMemMgr,
-            MemoryPermission permission,
+            KMemoryPermission permission,
             MemoryState      state,
             MemoryState      state,
             bool             copyData,
             bool             copyData,
             out ulong        dst)
             out ulong        dst)
@@ -1568,7 +1569,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
         private KernelResult GetPagesForMappingIntoAnotherProcess(
         private KernelResult GetPagesForMappingIntoAnotherProcess(
             ulong            address,
             ulong            address,
             ulong            size,
             ulong            size,
-            MemoryPermission permission,
+            KMemoryPermission permission,
             MemoryState      state,
             MemoryState      state,
             bool             copyData,
             bool             copyData,
             bool             aslrDisabled,
             bool             aslrDisabled,
@@ -1600,9 +1601,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                 default: return KernelResult.InvalidCombination;
                 default: return KernelResult.InvalidCombination;
             }
             }
 
 
-            MemoryPermission permissionMask = permission == MemoryPermission.ReadAndWrite
-                ? MemoryPermission.None
-                : MemoryPermission.Read;
+            KMemoryPermission permissionMask = permission == KMemoryPermission.ReadAndWrite
+                ? KMemoryPermission.None
+                : KMemoryPermission.Read;
 
 
             MemoryAttribute attributeMask = MemoryAttribute.Borrowed | MemoryAttribute.Uncached;
             MemoryAttribute attributeMask = MemoryAttribute.Borrowed | MemoryAttribute.Uncached;
 
 
@@ -1634,7 +1635,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
 
 
                 foreach (KMemoryInfo info in IterateOverRange(addressRounded, endAddrVisited))
                 foreach (KMemoryInfo info in IterateOverRange(addressRounded, endAddrVisited))
                 {
                 {
-                    if ((info.Permission & MemoryPermission.ReadAndWrite) != permissionMask && info.IpcRefCount == 0)
+                    if ((info.Permission & KMemoryPermission.ReadAndWrite) != permissionMask && info.IpcRefCount == 0)
                     {
                     {
                         ulong blockAddress = GetAddrInRange(info, addressRounded);
                         ulong blockAddress = GetAddrInRange(info, addressRounded);
                         ulong blockSize    = GetSizeInRange(info, addressRounded, endAddrVisited);
                         ulong blockSize    = GetSizeInRange(info, addressRounded, endAddrVisited);
@@ -1661,7 +1662,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
 
 
                 if (addressRounded < endAddrTruncated)
                 if (addressRounded < endAddrTruncated)
                 {
                 {
-                    foreach (KMemoryInfo info in IterateOverRange(addressTruncated, endAddrRounded))
+                    foreach (KMemoryInfo info in IterateOverRange(addressRounded, endAddrTruncated))
                     {
                     {
                         // Check if the block state matches what we expect.
                         // Check if the block state matches what we expect.
                         if ((info.State      & stateMask)     != stateMask  ||
                         if ((info.State      & stateMask)     != stateMask  ||
@@ -1678,7 +1679,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
 
 
                         ulong blockPagesCount = blockSize / PageSize;
                         ulong blockPagesCount = blockSize / PageSize;
 
 
-                        if ((info.Permission & MemoryPermission.ReadAndWrite) != permissionMask && info.IpcRefCount == 0)
+                        if ((info.Permission & KMemoryPermission.ReadAndWrite) != permissionMask && info.IpcRefCount == 0)
                         {
                         {
                             result = DoMmuOperation(
                             result = DoMmuOperation(
                                 blockAddress,
                                 blockAddress,
@@ -1784,7 +1785,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                 {
                 {
                     ulong unusedSizeBefore = address - addressTruncated;
                     ulong unusedSizeBefore = address - addressTruncated;
 
 
-                    _context.Memory.ZeroFill(dstFirstPagePa, unusedSizeBefore);
+                    _context.Memory.ZeroFill(GetDramAddressFromPa(dstFirstPagePa), unusedSizeBefore);
 
 
                     ulong copySize = addressRounded <= endAddr ? addressRounded - address : size;
                     ulong copySize = addressRounded <= endAddr ? addressRounded - address : size;
 
 
@@ -1803,7 +1804,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
 
 
                 if (unusedSizeAfter != 0)
                 if (unusedSizeAfter != 0)
                 {
                 {
-                    _context.Memory.ZeroFill(firstPageFillAddress, unusedSizeAfter);
+                    _context.Memory.ZeroFill(GetDramAddressFromPa(firstPageFillAddress), unusedSizeAfter);
                 }
                 }
 
 
                 if (pages.AddRange(dstFirstPagePa, 1) != KernelResult.Success)
                 if (pages.AddRange(dstFirstPagePa, 1) != KernelResult.Success)
@@ -1865,7 +1866,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     unusedSizeAfter = PageSize;
                     unusedSizeAfter = PageSize;
                 }
                 }
 
 
-                _context.Memory.ZeroFill(lastPageFillAddr, unusedSizeAfter);
+                _context.Memory.ZeroFill(GetDramAddressFromPa(lastPageFillAddr), unusedSizeAfter);
 
 
                 if (pages.AddRange(dstLastPagePa, 1) != KernelResult.Success)
                 if (pages.AddRange(dstLastPagePa, 1) != KernelResult.Success)
                 {
                 {
@@ -1897,7 +1898,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
         private KernelResult MapPagesFromAnotherProcess(
         private KernelResult MapPagesFromAnotherProcess(
             ulong            size,
             ulong            size,
             ulong            address,
             ulong            address,
-            MemoryPermission permission,
+            KMemoryPermission permission,
             MemoryState      state,
             MemoryState      state,
             KPageList        pageList,
             KPageList        pageList,
             out ulong        dst)
             out ulong        dst)
@@ -1975,8 +1976,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     size,
                     size,
                     MemoryState.Mask,
                     MemoryState.Mask,
                     state,
                     state,
-                    MemoryPermission.Read,
-                    MemoryPermission.Read,
+                    KMemoryPermission.Read,
+                    KMemoryPermission.Read,
                     MemoryAttribute.Mask,
                     MemoryAttribute.Mask,
                     MemoryAttribute.None,
                     MemoryAttribute.None,
                     MemoryAttribute.IpcAndDeviceMapped,
                     MemoryAttribute.IpcAndDeviceMapped,
@@ -1996,14 +1997,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
 
 
                     ulong pagesCount = (endAddrRounded - addressTruncated) / PageSize;
                     ulong pagesCount = (endAddrRounded - addressTruncated) / PageSize;
 
 
-                    KernelResult result = DoMmuOperation(
-                        addressTruncated,
-                        pagesCount,
-                        0,
-                        false,
-                        MemoryPermission.None,
-                        MemoryOperation.Unmap);
-
                     // Free pages we had to create on-demand, if any of the buffer was not page aligned.
                     // Free pages we had to create on-demand, if any of the buffer was not page aligned.
                     // Real kernel has page ref counting, so this is done as part of the unmap operation.
                     // Real kernel has page ref counting, so this is done as part of the unmap operation.
                     if (addressTruncated != addressRounded)
                     if (addressTruncated != addressRounded)
@@ -2016,6 +2009,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                         FreeSinglePage(_memRegion, ConvertVaToPa(endAddrTruncated));
                         FreeSinglePage(_memRegion, ConvertVaToPa(endAddrTruncated));
                     }
                     }
 
 
+                    KernelResult result = DoMmuOperation(
+                        addressTruncated,
+                        pagesCount,
+                        0,
+                        false,
+                        KMemoryPermission.None,
+                        MemoryOperation.Unmap);
+
                     if (result == KernelResult.Success)
                     if (result == KernelResult.Success)
                     {
                     {
                         InsertBlock(addressTruncated, pagesCount, MemoryState.Unmapped);
                         InsertBlock(addressTruncated, pagesCount, MemoryState.Unmapped);
@@ -2037,7 +2038,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong addressRounded   = BitUtils.AlignUp  (address, PageSize);
             ulong addressRounded   = BitUtils.AlignUp  (address, PageSize);
             ulong endAddrTruncated = BitUtils.AlignDown(endAddr, PageSize);
             ulong endAddrTruncated = BitUtils.AlignDown(endAddr, PageSize);
 
 
-            ulong pagesCount = (endAddrTruncated - addressRounded) / PageSize;
+            ulong pagesCount = addressRounded < endAddrTruncated ? (endAddrTruncated - addressRounded) / PageSize : 0;
+
+            if (pagesCount == 0)
+            {
+                return KernelResult.Success;
+            }
 
 
             MemoryState stateMask;
             MemoryState stateMask;
 
 
@@ -2111,23 +2117,23 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                 size,
                 size,
                 MemoryState.IpcBufferAllowed,
                 MemoryState.IpcBufferAllowed,
                 MemoryState.IpcBufferAllowed,
                 MemoryState.IpcBufferAllowed,
-                MemoryPermission.Mask,
-                MemoryPermission.ReadAndWrite,
+                KMemoryPermission.Mask,
+                KMemoryPermission.ReadAndWrite,
                 MemoryAttribute.Mask,
                 MemoryAttribute.Mask,
                 MemoryAttribute.None,
                 MemoryAttribute.None,
-                MemoryPermission.None,
+                KMemoryPermission.None,
                 MemoryAttribute.Borrowed);
                 MemoryAttribute.Borrowed);
         }
         }
 
 
-        public KernelResult BorrowTransferMemory(KPageList pageList, ulong address, ulong size, MemoryPermission permission)
+        public KernelResult BorrowTransferMemory(KPageList pageList, ulong address, ulong size, KMemoryPermission permission)
         {
         {
             return SetAttributesAndChangePermission(
             return SetAttributesAndChangePermission(
                 address,
                 address,
                 size,
                 size,
                 MemoryState.TransferMemoryAllowed,
                 MemoryState.TransferMemoryAllowed,
                 MemoryState.TransferMemoryAllowed,
                 MemoryState.TransferMemoryAllowed,
-                MemoryPermission.Mask,
-                MemoryPermission.ReadAndWrite,
+                KMemoryPermission.Mask,
+                KMemoryPermission.ReadAndWrite,
                 MemoryAttribute.Mask,
                 MemoryAttribute.Mask,
                 MemoryAttribute.None,
                 MemoryAttribute.None,
                 permission,
                 permission,
@@ -2140,11 +2146,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong            size,
             ulong            size,
             MemoryState      stateMask,
             MemoryState      stateMask,
             MemoryState      stateExpected,
             MemoryState      stateExpected,
-            MemoryPermission permissionMask,
-            MemoryPermission permissionExpected,
+            KMemoryPermission permissionMask,
+            KMemoryPermission permissionExpected,
             MemoryAttribute  attributeMask,
             MemoryAttribute  attributeMask,
             MemoryAttribute  attributeExpected,
             MemoryAttribute  attributeExpected,
-            MemoryPermission newPermission,
+            KMemoryPermission newPermission,
             MemoryAttribute  attributeSetMask,
             MemoryAttribute  attributeSetMask,
             KPageList        pageList = null)
             KPageList        pageList = null)
         {
         {
@@ -2166,7 +2172,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     attributeExpected,
                     attributeExpected,
                     MemoryAttribute.IpcAndDeviceMapped,
                     MemoryAttribute.IpcAndDeviceMapped,
                     out MemoryState      oldState,
                     out MemoryState      oldState,
-                    out MemoryPermission oldPermission,
+                    out KMemoryPermission oldPermission,
                     out MemoryAttribute  oldAttribute))
                     out MemoryAttribute  oldAttribute))
                 {
                 {
                     ulong pagesCount = size / PageSize;
                     ulong pagesCount = size / PageSize;
@@ -2181,7 +2187,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                         return KernelResult.OutOfResource;
                         return KernelResult.OutOfResource;
                     }
                     }
 
 
-                    if (newPermission == MemoryPermission.None)
+                    if (newPermission == KMemoryPermission.None)
                     {
                     {
                         newPermission = oldPermission;
                         newPermission = oldPermission;
                     }
                     }
@@ -2222,11 +2228,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                 size,
                 size,
                 MemoryState.IpcBufferAllowed,
                 MemoryState.IpcBufferAllowed,
                 MemoryState.IpcBufferAllowed,
                 MemoryState.IpcBufferAllowed,
-                MemoryPermission.None,
-                MemoryPermission.None,
+                KMemoryPermission.None,
+                KMemoryPermission.None,
                 MemoryAttribute.Mask,
                 MemoryAttribute.Mask,
                 MemoryAttribute.Borrowed,
                 MemoryAttribute.Borrowed,
-                MemoryPermission.ReadAndWrite,
+                KMemoryPermission.ReadAndWrite,
                 MemoryAttribute.Borrowed);
                 MemoryAttribute.Borrowed);
         }
         }
 
 
@@ -2237,11 +2243,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                 size,
                 size,
                 MemoryState.TransferMemoryAllowed,
                 MemoryState.TransferMemoryAllowed,
                 MemoryState.TransferMemoryAllowed,
                 MemoryState.TransferMemoryAllowed,
-                MemoryPermission.None,
-                MemoryPermission.None,
+                KMemoryPermission.None,
+                KMemoryPermission.None,
                 MemoryAttribute.Mask,
                 MemoryAttribute.Mask,
                 MemoryAttribute.Borrowed,
                 MemoryAttribute.Borrowed,
-                MemoryPermission.ReadAndWrite,
+                KMemoryPermission.ReadAndWrite,
                 MemoryAttribute.Borrowed,
                 MemoryAttribute.Borrowed,
                 pageList);
                 pageList);
         }
         }
@@ -2251,11 +2257,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong            size,
             ulong            size,
             MemoryState      stateMask,
             MemoryState      stateMask,
             MemoryState      stateExpected,
             MemoryState      stateExpected,
-            MemoryPermission permissionMask,
-            MemoryPermission permissionExpected,
+            KMemoryPermission permissionMask,
+            KMemoryPermission permissionExpected,
             MemoryAttribute  attributeMask,
             MemoryAttribute  attributeMask,
             MemoryAttribute  attributeExpected,
             MemoryAttribute  attributeExpected,
-            MemoryPermission newPermission,
+            KMemoryPermission newPermission,
             MemoryAttribute  attributeClearMask,
             MemoryAttribute  attributeClearMask,
             KPageList        pageList = null)
             KPageList        pageList = null)
         {
         {
@@ -2277,7 +2283,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     attributeExpected,
                     attributeExpected,
                     MemoryAttribute.IpcAndDeviceMapped,
                     MemoryAttribute.IpcAndDeviceMapped,
                     out MemoryState      oldState,
                     out MemoryState      oldState,
-                    out MemoryPermission oldPermission,
+                    out KMemoryPermission oldPermission,
                     out MemoryAttribute  oldAttribute))
                     out MemoryAttribute  oldAttribute))
                 {
                 {
                     ulong pagesCount = size / PageSize;
                     ulong pagesCount = size / PageSize;
@@ -2299,7 +2305,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                         return KernelResult.OutOfResource;
                         return KernelResult.OutOfResource;
                     }
                     }
 
 
-                    if (newPermission == MemoryPermission.None)
+                    if (newPermission == KMemoryPermission.None)
                     {
                     {
                         newPermission = oldPermission;
                         newPermission = oldPermission;
                     }
                     }
@@ -2385,8 +2391,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                 size,
                 size,
                 MemoryState.Mask,
                 MemoryState.Mask,
                 MemoryState.Unmapped,
                 MemoryState.Unmapped,
-                MemoryPermission.Mask,
-                MemoryPermission.None,
+                KMemoryPermission.Mask,
+                KMemoryPermission.None,
                 MemoryAttribute.Mask,
                 MemoryAttribute.Mask,
                 MemoryAttribute.None,
                 MemoryAttribute.None,
                 MemoryAttribute.IpcAndDeviceMapped,
                 MemoryAttribute.IpcAndDeviceMapped,
@@ -2400,13 +2406,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong                size,
             ulong                size,
             MemoryState          stateMask,
             MemoryState          stateMask,
             MemoryState          stateExpected,
             MemoryState          stateExpected,
-            MemoryPermission     permissionMask,
-            MemoryPermission     permissionExpected,
+            KMemoryPermission     permissionMask,
+            KMemoryPermission     permissionExpected,
             MemoryAttribute      attributeMask,
             MemoryAttribute      attributeMask,
             MemoryAttribute      attributeExpected,
             MemoryAttribute      attributeExpected,
             MemoryAttribute      attributeIgnoreMask,
             MemoryAttribute      attributeIgnoreMask,
             out MemoryState      outState,
             out MemoryState      outState,
-            out MemoryPermission outPermission,
+            out KMemoryPermission outPermission,
             out MemoryAttribute  outAttribute)
             out MemoryAttribute  outAttribute)
         {
         {
             ulong endAddr = address + size;
             ulong endAddr = address + size;
@@ -2416,7 +2422,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             KMemoryInfo info = node.Value.GetInfo();
             KMemoryInfo info = node.Value.GetInfo();
 
 
             MemoryState      firstState      = info.State;
             MemoryState      firstState      = info.State;
-            MemoryPermission firstPermission = info.Permission;
+            KMemoryPermission firstPermission = info.Permission;
             MemoryAttribute  firstAttribute  = info.Attribute;
             MemoryAttribute  firstAttribute  = info.Attribute;
 
 
             do
             do
@@ -2432,7 +2438,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                     (firstPermission & permissionMask)      != permissionExpected)
                     (firstPermission & permissionMask)      != permissionExpected)
                 {
                 {
                     outState      = MemoryState.Unmapped;
                     outState      = MemoryState.Unmapped;
-                    outPermission = MemoryPermission.None;
+                    outPermission = KMemoryPermission.None;
                     outAttribute  = MemoryAttribute.None;
                     outAttribute  = MemoryAttribute.None;
 
 
                     return false;
                     return false;
@@ -2452,8 +2458,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong            size,
             ulong            size,
             MemoryState      stateMask,
             MemoryState      stateMask,
             MemoryState      stateExpected,
             MemoryState      stateExpected,
-            MemoryPermission permissionMask,
-            MemoryPermission permissionExpected,
+            KMemoryPermission permissionMask,
+            KMemoryPermission permissionExpected,
             MemoryAttribute  attributeMask,
             MemoryAttribute  attributeMask,
             MemoryAttribute  attributeExpected)
             MemoryAttribute  attributeExpected)
         {
         {
@@ -2490,10 +2496,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong            baseAddress,
             ulong            baseAddress,
             ulong            pagesCount,
             ulong            pagesCount,
             MemoryState      oldState,
             MemoryState      oldState,
-            MemoryPermission oldPermission,
+            KMemoryPermission oldPermission,
             MemoryAttribute  oldAttribute,
             MemoryAttribute  oldAttribute,
             MemoryState      newState,
             MemoryState      newState,
-            MemoryPermission newPermission,
+            KMemoryPermission newPermission,
             MemoryAttribute  newAttribute)
             MemoryAttribute  newAttribute)
         {
         {
             // Insert new block on the list only on areas where the state
             // Insert new block on the list only on areas where the state
@@ -2553,13 +2559,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             }
             }
 
 
             _blockAllocator.Count += _blocks.Count - oldCount;
             _blockAllocator.Count += _blocks.Count - oldCount;
+
+            ValidateInternalState();
         }
         }
 
 
         private void InsertBlock(
         private void InsertBlock(
             ulong            baseAddress,
             ulong            baseAddress,
             ulong            pagesCount,
             ulong            pagesCount,
             MemoryState      state,
             MemoryState      state,
-            MemoryPermission permission = MemoryPermission.None,
+            KMemoryPermission permission = KMemoryPermission.None,
             MemoryAttribute  attribute  = MemoryAttribute.None)
             MemoryAttribute  attribute  = MemoryAttribute.None)
         {
         {
             // Inserts new block at the list, replacing and splitting
             // Inserts new block at the list, replacing and splitting
@@ -2605,25 +2613,27 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             }
             }
 
 
             _blockAllocator.Count += _blocks.Count - oldCount;
             _blockAllocator.Count += _blocks.Count - oldCount;
+
+            ValidateInternalState();
         }
         }
 
 
-        private static void SetIpcMappingPermissions(KMemoryBlock block, MemoryPermission permission)
+        private static void SetIpcMappingPermissions(KMemoryBlock block, KMemoryPermission permission)
         {
         {
             block.SetIpcMappingPermission(permission);
             block.SetIpcMappingPermission(permission);
         }
         }
 
 
-        private static void RestoreIpcMappingPermissions(KMemoryBlock block, MemoryPermission permission)
+        private static void RestoreIpcMappingPermissions(KMemoryBlock block, KMemoryPermission permission)
         {
         {
             block.RestoreIpcMappingPermission();
             block.RestoreIpcMappingPermission();
         }
         }
 
 
-        private delegate void BlockMutator(KMemoryBlock block, MemoryPermission newPerm);
+        private delegate void BlockMutator(KMemoryBlock block, KMemoryPermission newPerm);
 
 
         private void InsertBlock(
         private void InsertBlock(
             ulong            baseAddress,
             ulong            baseAddress,
             ulong            pagesCount,
             ulong            pagesCount,
             BlockMutator     blockMutate,
             BlockMutator     blockMutate,
-            MemoryPermission permission = MemoryPermission.None)
+            KMemoryPermission permission = KMemoryPermission.None)
         {
         {
             // Inserts new block at the list, replacing and splitting
             // Inserts new block at the list, replacing and splitting
             // existing blocks as needed, then calling the callback
             // existing blocks as needed, then calling the callback
@@ -2671,6 +2681,31 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             }
             }
 
 
             _blockAllocator.Count += _blocks.Count - oldCount;
             _blockAllocator.Count += _blocks.Count - oldCount;
+
+            ValidateInternalState();
+        }
+
+        [Conditional("DEBUG")]
+        private void ValidateInternalState()
+        {
+            ulong expectedAddress = 0;
+
+            LinkedListNode<KMemoryBlock> node = _blocks.First;
+
+            while (node != null)
+            {
+                LinkedListNode<KMemoryBlock> newNode = node;
+
+                KMemoryBlock currBlock = node.Value;
+
+                Debug.Assert(currBlock.BaseAddress == expectedAddress);
+
+                expectedAddress = currBlock.BaseAddress + currBlock.PagesCount * PageSize;
+
+                node = newNode.Next;
+            }
+
+            Debug.Assert(expectedAddress == AddrSpaceEnd);
         }
         }
 
 
         private LinkedListNode<KMemoryBlock> MergeEqualStateNeighbors(LinkedListNode<KMemoryBlock> node)
         private LinkedListNode<KMemoryBlock> MergeEqualStateNeighbors(LinkedListNode<KMemoryBlock> node)
@@ -2876,13 +2911,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             return null;
             return null;
         }
         }
 
 
-        private bool ValidateRegionForState(ulong address, ulong size, MemoryState state)
+        public bool CanContain(ulong address, ulong size, MemoryState state)
         {
         {
             ulong endAddr = address + size;
             ulong endAddr = address + size;
 
 
-            ulong regionBaseAddr = GetBaseAddrForState(state);
-
-            ulong regionEndAddr = regionBaseAddr + GetSizeForState(state);
+            ulong regionBaseAddr = GetBaseAddress(state);
+            ulong regionEndAddr = regionBaseAddr + GetSize(state);
 
 
             bool InsideRegion()
             bool InsideRegion()
             {
             {
@@ -2891,17 +2925,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                        endAddr - 1    <= regionEndAddr - 1;
                        endAddr - 1    <= regionEndAddr - 1;
             }
             }
 
 
-            bool OutsideHeapRegion()
-            {
-                return endAddr <= HeapRegionStart ||
-                       address >= HeapRegionEnd;
-            }
-
-            bool OutsideMapRegion()
-            {
-                return endAddr <= AliasRegionStart ||
-                       address >= AliasRegionEnd;
-            }
+            bool OutsideHeapRegion() => endAddr <= HeapRegionStart ||  address >= HeapRegionEnd;
+            bool OutsideAliasRegion() => endAddr <= AliasRegionStart || address >= AliasRegionEnd;
 
 
             switch (state)
             switch (state)
             {
             {
@@ -2919,10 +2944,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                 case MemoryState.ProcessMemory:
                 case MemoryState.ProcessMemory:
                 case MemoryState.CodeReadOnly:
                 case MemoryState.CodeReadOnly:
                 case MemoryState.CodeWritable:
                 case MemoryState.CodeWritable:
-                    return InsideRegion() && OutsideHeapRegion() && OutsideMapRegion();
+                    return InsideRegion() && OutsideHeapRegion() && OutsideAliasRegion();
 
 
                 case MemoryState.Heap:
                 case MemoryState.Heap:
-                    return InsideRegion() && OutsideMapRegion();
+                    return InsideRegion() && OutsideAliasRegion();
 
 
                 case MemoryState.IpcBuffer0:
                 case MemoryState.IpcBuffer0:
                 case MemoryState.IpcBuffer1:
                 case MemoryState.IpcBuffer1:
@@ -2936,7 +2961,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             throw new ArgumentException($"Invalid state value \"{state}\".");
             throw new ArgumentException($"Invalid state value \"{state}\".");
         }
         }
 
 
-        private ulong GetBaseAddrForState(MemoryState state)
+        private ulong GetBaseAddress(MemoryState state)
         {
         {
             switch (state)
             switch (state)
             {
             {
@@ -2975,7 +3000,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             throw new ArgumentException($"Invalid state value \"{state}\".");
             throw new ArgumentException($"Invalid state value \"{state}\".");
         }
         }
 
 
-        private ulong GetSizeForState(MemoryState state)
+        private ulong GetSize(MemoryState state)
         {
         {
             switch (state)
             switch (state)
             {
             {
@@ -3050,7 +3075,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             }
             }
         }
         }
 
 
-        private KernelResult MapPages(ulong address, KPageList pageList, MemoryPermission permission)
+        private KernelResult MapPages(ulong address, KPageList pageList, KMemoryPermission permission)
         {
         {
             ulong currAddr = address;
             ulong currAddr = address;
 
 
@@ -3090,11 +3115,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                 pagesCount,
                 pagesCount,
                 0,
                 0,
                 false,
                 false,
-                MemoryPermission.None,
+                KMemoryPermission.None,
                 MemoryOperation.Unmap);
                 MemoryOperation.Unmap);
         }
         }
 
 
-        private KernelResult MmuChangePermission(ulong address, ulong pagesCount, MemoryPermission permission)
+        private KernelResult MmuChangePermission(ulong address, ulong pagesCount, KMemoryPermission permission)
         {
         {
             return DoMmuOperation(
             return DoMmuOperation(
                 address,
                 address,
@@ -3110,7 +3135,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong            pagesCount,
             ulong            pagesCount,
             ulong            srcPa,
             ulong            srcPa,
             bool             map,
             bool             map,
-            MemoryPermission permission,
+            KMemoryPermission permission,
             MemoryOperation  operation)
             MemoryOperation  operation)
         {
         {
             if (map != (operation == MemoryOperation.MapPa))
             if (map != (operation == MemoryOperation.MapPa))
@@ -3171,7 +3196,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong            address,
             ulong            address,
             ulong            pagesCount,
             ulong            pagesCount,
             KPageList        pageList,
             KPageList        pageList,
-            MemoryPermission permission,
+            KMemoryPermission permission,
             MemoryOperation  operation)
             MemoryOperation  operation)
         {
         {
             if (operation != MemoryOperation.MapVa)
             if (operation != MemoryOperation.MapVa)

+ 6 - 6
Ryujinx.HLE/HOS/Kernel/Memory/KSharedMemory.cs

@@ -10,15 +10,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
 
 
         private readonly long _ownerPid;
         private readonly long _ownerPid;
 
 
-        private readonly MemoryPermission _ownerPermission;
-        private readonly MemoryPermission _userPermission;
+        private readonly KMemoryPermission _ownerPermission;
+        private readonly KMemoryPermission _userPermission;
 
 
         public KSharedMemory(
         public KSharedMemory(
             KernelContext    context,
             KernelContext    context,
             KPageList        pageList,
             KPageList        pageList,
             long             ownerPid,
             long             ownerPid,
-            MemoryPermission ownerPermission,
-            MemoryPermission userPermission) : base(context)
+            KMemoryPermission ownerPermission,
+            KMemoryPermission userPermission) : base(context)
         {
         {
             _pageList        = pageList;
             _pageList        = pageList;
             _ownerPid        = ownerPid;
             _ownerPid        = ownerPid;
@@ -31,7 +31,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             ulong            address,
             ulong            address,
             ulong            size,
             ulong            size,
             KProcess         process,
             KProcess         process,
-            MemoryPermission permission)
+            KMemoryPermission permission)
         {
         {
             ulong pagesCountRounded = BitUtils.DivRoundUp(size, KMemoryManager.PageSize);
             ulong pagesCountRounded = BitUtils.DivRoundUp(size, KMemoryManager.PageSize);
 
 
@@ -40,7 +40,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
                 return KernelResult.InvalidSize;
                 return KernelResult.InvalidSize;
             }
             }
 
 
-            MemoryPermission expectedPermission = process.Pid == _ownerPid
+            KMemoryPermission expectedPermission = process.Pid == _ownerPid
                 ? _ownerPermission
                 ? _ownerPermission
                 : _userPermission;
                 : _userPermission;
 
 

+ 5 - 2
Ryujinx.HLE/HOS/Kernel/Memory/KTransferMemory.cs

@@ -8,12 +8,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
     {
     {
         private KProcess _creator;
         private KProcess _creator;
 
 
+        // TODO: Remove when we no longer need to read it from the owner directly.
+        public KProcess Creator => _creator;
+
         private readonly KPageList _pageList;
         private readonly KPageList _pageList;
 
 
         public ulong Address { get; private set; }
         public ulong Address { get; private set; }
         public ulong Size => _pageList.GetPagesCount() * KMemoryManager.PageSize;
         public ulong Size => _pageList.GetPagesCount() * KMemoryManager.PageSize;
 
 
-        public MemoryPermission Permission { get; private set; }
+        public KMemoryPermission Permission { get; private set; }
 
 
         private bool _hasBeenInitialized;
         private bool _hasBeenInitialized;
         private bool _isMapped;
         private bool _isMapped;
@@ -23,7 +26,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
             _pageList = new KPageList();
             _pageList = new KPageList();
         }
         }
 
 
-        public KernelResult Initialize(ulong address, ulong size, MemoryPermission permission)
+        public KernelResult Initialize(ulong address, ulong size, KMemoryPermission permission)
         {
         {
             KProcess creator = KernelContext.Scheduler.GetCurrentProcess();
             KProcess creator = KernelContext.Scheduler.GetCurrentProcess();
 
 

+ 1 - 1
Ryujinx.HLE/HOS/Kernel/Memory/MemoryPermission.cs

@@ -3,7 +3,7 @@ using System;
 namespace Ryujinx.HLE.HOS.Kernel.Memory
 namespace Ryujinx.HLE.HOS.Kernel.Memory
 {
 {
     [Flags]
     [Flags]
-    enum MemoryPermission : byte
+    enum KMemoryPermission : byte
     {
     {
         None = 0,
         None = 0,
         Mask = 0xff,
         Mask = 0xff,

+ 5 - 5
Ryujinx.HLE/HOS/Kernel/Process/HleProcessDebugger.cs

@@ -1,7 +1,7 @@
-using Ryujinx.Cpu;
 using Ryujinx.HLE.HOS.Diagnostics.Demangler;
 using Ryujinx.HLE.HOS.Diagnostics.Demangler;
 using Ryujinx.HLE.HOS.Kernel.Memory;
 using Ryujinx.HLE.HOS.Kernel.Memory;
 using Ryujinx.HLE.Loaders.Elf;
 using Ryujinx.HLE.Loaders.Elf;
+using Ryujinx.Memory;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
 using System.Text;
 using System.Text;
@@ -224,7 +224,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                     break;
                     break;
                 }
                 }
 
 
-                if (info.State == MemoryState.CodeStatic && info.Permission == MemoryPermission.ReadAndExecute)
+                if (info.State == MemoryState.CodeStatic && info.Permission == KMemoryPermission.ReadAndExecute)
                 {
                 {
                     LoadMod0Symbols(_owner.CpuMemory, info.Address);
                     LoadMod0Symbols(_owner.CpuMemory, info.Address);
                 }
                 }
@@ -235,7 +235,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
             }
             }
         }
         }
 
 
-        private void LoadMod0Symbols(MemoryManager memory, ulong textOffset)
+        private void LoadMod0Symbols(IVirtualMemoryManager memory, ulong textOffset)
         {
         {
             ulong mod0Offset = textOffset + memory.Read<uint>(textOffset + 4);
             ulong mod0Offset = textOffset + memory.Read<uint>(textOffset + 4);
 
 
@@ -319,7 +319,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
             }
             }
         }
         }
 
 
-        private ElfSymbol GetSymbol64(MemoryManager memory, ulong address, ulong strTblAddr)
+        private ElfSymbol GetSymbol64(IVirtualMemoryManager memory, ulong address, ulong strTblAddr)
         {
         {
             ElfSymbol64 sym = memory.Read<ElfSymbol64>(address);
             ElfSymbol64 sym = memory.Read<ElfSymbol64>(address);
 
 
@@ -335,7 +335,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
             return new ElfSymbol(name, sym.Info, sym.Other, sym.SectionIndex, sym.ValueAddress, sym.Size);
             return new ElfSymbol(name, sym.Info, sym.Other, sym.SectionIndex, sym.ValueAddress, sym.Size);
         }
         }
 
 
-        private ElfSymbol GetSymbol32(MemoryManager memory, ulong address, ulong strTblAddr)
+        private ElfSymbol GetSymbol32(IVirtualMemoryManager memory, ulong address, ulong strTblAddr)
         {
         {
             ElfSymbol32 sym = memory.Read<ElfSymbol32>(address);
             ElfSymbol32 sym = memory.Read<ElfSymbol32>(address);
 
 

+ 13 - 0
Ryujinx.HLE/HOS/Kernel/Process/IProcessContext.cs

@@ -0,0 +1,13 @@
+using ARMeilleure.State;
+using Ryujinx.Memory;
+using System;
+
+namespace Ryujinx.HLE.HOS.Kernel.Process
+{
+    interface IProcessContext : IDisposable
+    {
+        IVirtualMemoryManager AddressSpace { get; }
+
+        void Execute(ExecutionContext context, ulong codeAddress);
+    }
+}

+ 10 - 0
Ryujinx.HLE/HOS/Kernel/Process/IProcessContextFactory.cs

@@ -0,0 +1,10 @@
+using Ryujinx.Cpu;
+using Ryujinx.Memory;
+
+namespace Ryujinx.HLE.HOS.Kernel.Process
+{
+    interface IProcessContextFactory
+    {
+        IProcessContext Create(MemoryBlock backingMemory, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler);
+    }
+}

+ 97 - 137
Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs

@@ -6,6 +6,7 @@ using Ryujinx.HLE.Exceptions;
 using Ryujinx.HLE.HOS.Kernel.Common;
 using Ryujinx.HLE.HOS.Kernel.Common;
 using Ryujinx.HLE.HOS.Kernel.Memory;
 using Ryujinx.HLE.HOS.Kernel.Memory;
 using Ryujinx.HLE.HOS.Kernel.Threading;
 using Ryujinx.HLE.HOS.Kernel.Threading;
+using Ryujinx.Memory;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
@@ -15,13 +16,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 {
 {
     class KProcess : KSynchronizationObject
     class KProcess : KSynchronizationObject
     {
     {
-        public const int KernelVersionMajor    = 10;
-        public const int KernelVersionMinor    = 4;
+        public const int KernelVersionMajor = 10;
+        public const int KernelVersionMinor = 4;
         public const int KernelVersionRevision = 0;
         public const int KernelVersionRevision = 0;
 
 
         public const int KernelVersionPacked =
         public const int KernelVersionPacked =
-            (KernelVersionMajor    << 19) |
-            (KernelVersionMinor    << 15) |
+            (KernelVersionMajor << 19) |
+            (KernelVersionMinor << 15) |
             (KernelVersionRevision << 0);
             (KernelVersionRevision << 0);
 
 
         public KMemoryManager MemoryManager { get; private set; }
         public KMemoryManager MemoryManager { get; private set; }
@@ -47,27 +48,27 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
         public long[] RandomEntropy { get; private set; }
         public long[] RandomEntropy { get; private set; }
 
 
         private bool _signaled;
         private bool _signaled;
-        private bool _useSystemMemBlocks;
 
 
         public string Name { get; private set; }
         public string Name { get; private set; }
 
 
         private int _threadCount;
         private int _threadCount;
 
 
-        public int MmuFlags { get; private set; }
+        public ProcessCreationFlags Flags { get; private set; }
 
 
         private MemoryRegion _memRegion;
         private MemoryRegion _memRegion;
 
 
         public KProcessCapabilities Capabilities { get; private set; }
         public KProcessCapabilities Capabilities { get; private set; }
 
 
         public ulong TitleId { get; private set; }
         public ulong TitleId { get; private set; }
-        public long  Pid     { get; private set; }
+        public long Pid { get; private set; }
 
 
-        private long  _creationTimestamp;
+        private long _creationTimestamp;
         private ulong _entrypoint;
         private ulong _entrypoint;
+        private ThreadStart _customThreadStart;
         private ulong _imageSize;
         private ulong _imageSize;
         private ulong _mainThreadStackSize;
         private ulong _mainThreadStackSize;
         private ulong _memoryUsageCapacity;
         private ulong _memoryUsageCapacity;
-        private int   _version;
+        private int _version;
 
 
         public KHandleTable HandleTable { get; private set; }
         public KHandleTable HandleTable { get; private set; }
 
 
@@ -77,14 +78,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 
 
         public bool IsPaused { get; private set; }
         public bool IsPaused { get; private set; }
 
 
-        public MemoryManager CpuMemory { get; private set; }
-        public CpuContext CpuContext { get; private set; }
+        private IProcessContextFactory _contextFactory;
+        public IProcessContext Context { get; private set; }
+        public IVirtualMemoryManager CpuMemory => Context.AddressSpace;
 
 
         public HleProcessDebugger Debugger { get; private set; }
         public HleProcessDebugger Debugger { get; private set; }
 
 
         public KProcess(KernelContext context) : base(context)
         public KProcess(KernelContext context) : base(context)
         {
         {
-            _processLock   = new object();
+            _processLock = new object();
             _threadingLock = new object();
             _threadingLock = new object();
 
 
             AddressArbiter = new KAddressArbiter(context);
             AddressArbiter = new KAddressArbiter(context);
@@ -96,6 +98,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 
 
             RandomEntropy = new long[KScheduler.CpuCoresCount];
             RandomEntropy = new long[KScheduler.CpuCoresCount];
 
 
+            // TODO: Remove once we no longer need to initialize it externally.
+            HandleTable = new KHandleTable(context);
+
             _threads = new LinkedList<KThread>();
             _threads = new LinkedList<KThread>();
 
 
             Debugger = new HleProcessDebugger(this);
             Debugger = new HleProcessDebugger(this);
@@ -103,25 +108,27 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 
 
         public KernelResult InitializeKip(
         public KernelResult InitializeKip(
             ProcessCreationInfo creationInfo,
             ProcessCreationInfo creationInfo,
-            int[]               caps,
-            KPageList           pageList,
-            KResourceLimit      resourceLimit,
-            MemoryRegion        memRegion)
+            ReadOnlySpan<int> capabilities,
+            KPageList pageList,
+            KResourceLimit resourceLimit,
+            MemoryRegion memRegion,
+            IProcessContextFactory contextFactory)
         {
         {
             ResourceLimit = resourceLimit;
             ResourceLimit = resourceLimit;
-            _memRegion     = memRegion;
+            _memRegion = memRegion;
+            _contextFactory = contextFactory ?? new ProcessContextFactory();
 
 
-            AddressSpaceType addrSpaceType = (AddressSpaceType)((creationInfo.MmuFlags >> 1) & 7);
+            AddressSpaceType addrSpaceType = (AddressSpaceType)((int)(creationInfo.Flags & ProcessCreationFlags.AddressSpaceMask) >> (int)ProcessCreationFlags.AddressSpaceShift);
 
 
-            InitializeMemoryManager(addrSpaceType, memRegion);
+            InitializeMemoryManager(creationInfo.Flags);
 
 
-            bool aslrEnabled = ((creationInfo.MmuFlags >> 5) & 1) != 0;
+            bool aslrEnabled = creationInfo.Flags.HasFlag(ProcessCreationFlags.EnableAslr);
 
 
             ulong codeAddress = creationInfo.CodeAddress;
             ulong codeAddress = creationInfo.CodeAddress;
 
 
             ulong codeSize = (ulong)creationInfo.CodePagesCount * KMemoryManager.PageSize;
             ulong codeSize = (ulong)creationInfo.CodePagesCount * KMemoryManager.PageSize;
 
 
-            KMemoryBlockAllocator memoryBlockAllocator = (MmuFlags & 0x40) != 0
+            KMemoryBlockAllocator memoryBlockAllocator = creationInfo.Flags.HasFlag(ProcessCreationFlags.IsApplication)
                 ? KernelContext.LargeMemoryBlockAllocator
                 ? KernelContext.LargeMemoryBlockAllocator
                 : KernelContext.SmallMemoryBlockAllocator;
                 : KernelContext.SmallMemoryBlockAllocator;
 
 
@@ -139,7 +146,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                 return result;
                 return result;
             }
             }
 
 
-            if (!ValidateCodeAddressAndSize(codeAddress, codeSize))
+            if (!MemoryManager.CanContain(codeAddress, codeSize, MemoryState.CodeStatic))
             {
             {
                 return KernelResult.InvalidMemRange;
                 return KernelResult.InvalidMemRange;
             }
             }
@@ -148,14 +155,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                 codeAddress,
                 codeAddress,
                 pageList,
                 pageList,
                 MemoryState.CodeStatic,
                 MemoryState.CodeStatic,
-                MemoryPermission.None);
+                KMemoryPermission.None);
 
 
             if (result != KernelResult.Success)
             if (result != KernelResult.Success)
             {
             {
                 return result;
                 return result;
             }
             }
 
 
-            result = Capabilities.InitializeForKernel(caps, MemoryManager);
+            result = Capabilities.InitializeForKernel(capabilities, MemoryManager);
 
 
             if (result != KernelResult.Success)
             if (result != KernelResult.Success)
             {
             {
@@ -176,14 +183,17 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 
 
         public KernelResult Initialize(
         public KernelResult Initialize(
             ProcessCreationInfo creationInfo,
             ProcessCreationInfo creationInfo,
-            int[]               caps,
-            KResourceLimit      resourceLimit,
-            MemoryRegion        memRegion)
+            ReadOnlySpan<int> capabilities,
+            KResourceLimit resourceLimit,
+            MemoryRegion memRegion,
+            IProcessContextFactory contextFactory,
+            ThreadStart customThreadStart = null)
         {
         {
             ResourceLimit = resourceLimit;
             ResourceLimit = resourceLimit;
-            _memRegion    = memRegion;
+            _memRegion = memRegion;
+            _contextFactory = contextFactory ?? new ProcessContextFactory();
 
 
-            ulong personalMmHeapSize = GetPersonalMmHeapSize((ulong)creationInfo.PersonalMmHeapPagesCount, memRegion);
+            ulong personalMmHeapSize = GetPersonalMmHeapSize((ulong)creationInfo.SystemResourcePagesCount, memRegion);
 
 
             ulong codePagesCount = (ulong)creationInfo.CodePagesCount;
             ulong codePagesCount = (ulong)creationInfo.CodePagesCount;
 
 
@@ -205,7 +215,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                 }
                 }
             }
             }
 
 
-            PersonalMmHeapPagesCount = (ulong)creationInfo.PersonalMmHeapPagesCount;
+            PersonalMmHeapPagesCount = (ulong)creationInfo.SystemResourcePagesCount;
 
 
             KMemoryBlockAllocator memoryBlockAllocator;
             KMemoryBlockAllocator memoryBlockAllocator;
 
 
@@ -215,16 +225,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
             }
             }
             else
             else
             {
             {
-                memoryBlockAllocator = (MmuFlags & 0x40) != 0
+                memoryBlockAllocator = creationInfo.Flags.HasFlag(ProcessCreationFlags.IsApplication)
                     ? KernelContext.LargeMemoryBlockAllocator
                     ? KernelContext.LargeMemoryBlockAllocator
                     : KernelContext.SmallMemoryBlockAllocator;
                     : KernelContext.SmallMemoryBlockAllocator;
             }
             }
 
 
-            AddressSpaceType addrSpaceType = (AddressSpaceType)((creationInfo.MmuFlags >> 1) & 7);
+            AddressSpaceType addrSpaceType = (AddressSpaceType)((int)(creationInfo.Flags & ProcessCreationFlags.AddressSpaceMask) >> (int)ProcessCreationFlags.AddressSpaceShift);
 
 
-            InitializeMemoryManager(addrSpaceType, memRegion);
+            InitializeMemoryManager(creationInfo.Flags);
 
 
-            bool aslrEnabled = ((creationInfo.MmuFlags >> 5) & 1) != 0;
+            bool aslrEnabled = creationInfo.Flags.HasFlag(ProcessCreationFlags.EnableAslr);
 
 
             ulong codeAddress = creationInfo.CodeAddress;
             ulong codeAddress = creationInfo.CodeAddress;
 
 
@@ -246,7 +256,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                 return result;
                 return result;
             }
             }
 
 
-            if (!ValidateCodeAddressAndSize(codeAddress, codeSize))
+            if (!MemoryManager.CanContain(codeAddress, codeSize, MemoryState.CodeStatic))
             {
             {
                 CleanUpForError();
                 CleanUpForError();
 
 
@@ -257,7 +267,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                 codeAddress,
                 codeAddress,
                 codePagesCount,
                 codePagesCount,
                 MemoryState.CodeStatic,
                 MemoryState.CodeStatic,
-                MemoryPermission.None);
+                KMemoryPermission.None);
 
 
             if (result != KernelResult.Success)
             if (result != KernelResult.Success)
             {
             {
@@ -266,7 +276,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                 return result;
                 return result;
             }
             }
 
 
-            result = Capabilities.InitializeForUser(caps, MemoryManager);
+            result = Capabilities.InitializeForUser(capabilities, MemoryManager);
 
 
             if (result != KernelResult.Success)
             if (result != KernelResult.Success)
             {
             {
@@ -289,57 +299,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                 CleanUpForError();
                 CleanUpForError();
             }
             }
 
 
-            return result;
-        }
-
-        private bool ValidateCodeAddressAndSize(ulong address, ulong size)
-        {
-            ulong codeRegionStart;
-            ulong codeRegionSize;
-
-            switch (MemoryManager.AddrSpaceWidth)
-            {
-                case 32:
-                    codeRegionStart = 0x200000;
-                    codeRegionSize  = 0x3fe00000;
-                    break;
-
-                case 36:
-                    codeRegionStart = 0x8000000;
-                    codeRegionSize  = 0x78000000;
-                    break;
-
-                case 39:
-                    codeRegionStart = 0x8000000;
-                    codeRegionSize  = 0x7ff8000000;
-                    break;
-
-                default: throw new InvalidOperationException("Invalid address space width on memory manager.");
-            }
-
-            ulong endAddr = address + size;
-
-            ulong codeRegionEnd = codeRegionStart + codeRegionSize;
-
-            if (endAddr     <= address ||
-                endAddr - 1 >  codeRegionEnd - 1)
-            {
-                return false;
-            }
-
-            if (MemoryManager.InsideHeapRegion (address, size) ||
-                MemoryManager.InsideAliasRegion(address, size))
-            {
-                return false;
-            }
+            _customThreadStart = customThreadStart;
 
 
-            return true;
+            return result;
         }
         }
 
 
         private KernelResult ParseProcessInfo(ProcessCreationInfo creationInfo)
         private KernelResult ParseProcessInfo(ProcessCreationInfo creationInfo)
         {
         {
             // Ensure that the current kernel version is equal or above to the minimum required.
             // Ensure that the current kernel version is equal or above to the minimum required.
-            uint requiredKernelVersionMajor =  (uint)Capabilities.KernelReleaseVersion >> 19;
+            uint requiredKernelVersionMajor = (uint)Capabilities.KernelReleaseVersion >> 19;
             uint requiredKernelVersionMinor = ((uint)Capabilities.KernelReleaseVersion >> 15) & 0xf;
             uint requiredKernelVersionMinor = ((uint)Capabilities.KernelReleaseVersion >> 15) & 0xf;
 
 
             if (KernelContext.EnableVersionChecks)
             if (KernelContext.EnableVersionChecks)
@@ -377,31 +345,29 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 
 
             _creationTimestamp = PerformanceCounter.ElapsedMilliseconds;
             _creationTimestamp = PerformanceCounter.ElapsedMilliseconds;
 
 
-            MmuFlags    = creationInfo.MmuFlags;
-            _version   = creationInfo.Version;
-            TitleId     = creationInfo.TitleId;
+            Flags = creationInfo.Flags;
+            _version = creationInfo.Version;
+            TitleId = creationInfo.TitleId;
             _entrypoint = creationInfo.CodeAddress;
             _entrypoint = creationInfo.CodeAddress;
-            _imageSize  = (ulong)creationInfo.CodePagesCount * KMemoryManager.PageSize;
-
-            _useSystemMemBlocks = ((MmuFlags >> 6) & 1) != 0;
+            _imageSize = (ulong)creationInfo.CodePagesCount * KMemoryManager.PageSize;
 
 
-            switch ((AddressSpaceType)((MmuFlags >> 1) & 7))
+            switch (Flags & ProcessCreationFlags.AddressSpaceMask)
             {
             {
-                case AddressSpaceType.Addr32Bits:
-                case AddressSpaceType.Addr36Bits:
-                case AddressSpaceType.Addr39Bits:
+                case ProcessCreationFlags.AddressSpace32Bit:
+                case ProcessCreationFlags.AddressSpace64BitDeprecated:
+                case ProcessCreationFlags.AddressSpace64Bit:
                     _memoryUsageCapacity = MemoryManager.HeapRegionEnd -
                     _memoryUsageCapacity = MemoryManager.HeapRegionEnd -
                                            MemoryManager.HeapRegionStart;
                                            MemoryManager.HeapRegionStart;
                     break;
                     break;
 
 
-                case AddressSpaceType.Addr32BitsNoMap:
+                case ProcessCreationFlags.AddressSpace32BitWithoutAlias:
                     _memoryUsageCapacity = MemoryManager.HeapRegionEnd -
                     _memoryUsageCapacity = MemoryManager.HeapRegionEnd -
                                            MemoryManager.HeapRegionStart +
                                            MemoryManager.HeapRegionStart +
                                            MemoryManager.AliasRegionEnd -
                                            MemoryManager.AliasRegionEnd -
                                            MemoryManager.AliasRegionStart;
                                            MemoryManager.AliasRegionStart;
                     break;
                     break;
 
 
-                default: throw new InvalidOperationException($"Invalid MMU flags value 0x{MmuFlags:x2}.");
+                default: throw new InvalidOperationException($"Invalid MMU flags value 0x{Flags:x2}.");
             }
             }
 
 
             GenerateRandomEntropy();
             GenerateRandomEntropy();
@@ -469,7 +435,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
             }
             }
 
 
             ulong regionStart = MemoryManager.TlsIoRegionStart;
             ulong regionStart = MemoryManager.TlsIoRegionStart;
-            ulong regionSize  = MemoryManager.TlsIoRegionEnd - regionStart;
+            ulong regionSize = MemoryManager.TlsIoRegionEnd - regionStart;
 
 
             ulong regionPagesCount = regionSize / KMemoryManager.PageSize;
             ulong regionPagesCount = regionSize / KMemoryManager.PageSize;
 
 
@@ -481,7 +447,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                 regionStart,
                 regionStart,
                 regionPagesCount,
                 regionPagesCount,
                 MemoryState.ThreadLocal,
                 MemoryState.ThreadLocal,
-                MemoryPermission.ReadAndWrite,
+                KMemoryPermission.ReadAndWrite,
                 out ulong tlsPageVa);
                 out ulong tlsPageVa);
 
 
             if (result != KernelResult.Success)
             if (result != KernelResult.Success)
@@ -506,7 +472,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 
 
             KernelResult result = KernelResult.Success;
             KernelResult result = KernelResult.Success;
 
 
-            KTlsPageInfo pageInfo = null;
+            KTlsPageInfo pageInfo;
 
 
             if (_fullTlsPages.TryGetValue(tlsPageAddr, out pageInfo))
             if (_fullTlsPages.TryGetValue(tlsPageAddr, out pageInfo))
             {
             {
@@ -594,8 +560,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                 // Check if the needed size for the code and the stack will fit on the
                 // Check if the needed size for the code and the stack will fit on the
                 // memory usage capacity of this Process. Also check for possible overflow
                 // memory usage capacity of this Process. Also check for possible overflow
                 // on the above addition.
                 // on the above addition.
-                if (neededSize > _memoryUsageCapacity ||
-                    neededSize < stackSizeRounded)
+                if (neededSize > _memoryUsageCapacity || neededSize < stackSizeRounded)
                 {
                 {
                     threadResourceLimit?.Release(LimitableResource.Thread, 1);
                     threadResourceLimit?.Release(LimitableResource.Thread, 1);
 
 
@@ -646,7 +611,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                     ulong stackPagesCount = stackSizeRounded / KMemoryManager.PageSize;
                     ulong stackPagesCount = stackSizeRounded / KMemoryManager.PageSize;
 
 
                     ulong regionStart = MemoryManager.StackRegionStart;
                     ulong regionStart = MemoryManager.StackRegionStart;
-                    ulong regionSize  = MemoryManager.StackRegionEnd - regionStart;
+                    ulong regionSize = MemoryManager.StackRegionEnd - regionStart;
 
 
                     ulong regionPagesCount = regionSize / KMemoryManager.PageSize;
                     ulong regionPagesCount = regionSize / KMemoryManager.PageSize;
 
 
@@ -658,7 +623,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                         regionStart,
                         regionStart,
                         regionPagesCount,
                         regionPagesCount,
                         MemoryState.Stack,
                         MemoryState.Stack,
-                        MemoryPermission.ReadAndWrite,
+                        KMemoryPermission.ReadAndWrite,
                         out ulong stackBottom);
                         out ulong stackBottom);
 
 
                     if (result != KernelResult.Success)
                     if (result != KernelResult.Success)
@@ -703,7 +668,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                     stackTop,
                     stackTop,
                     mainThreadPriority,
                     mainThreadPriority,
                     DefaultCpuCore,
                     DefaultCpuCore,
-                    this);
+                    this,
+                    ThreadType.User,
+                    _customThreadStart);
 
 
                 if (result != KernelResult.Success)
                 if (result != KernelResult.Success)
                 {
                 {
@@ -730,20 +697,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 
 
                 SetState(newState);
                 SetState(newState);
 
 
-                // TODO: We can't call KThread.Start from a non-guest thread.
-                // We will need to make some changes to allow the creation of
-                // dummy threads that will be used to initialize the current
-                // thread on KCoreContext so that GetCurrentThread doesn't fail.
-                /* Result = MainThread.Start();
+                result = mainThread.Start();
 
 
-                if (Result != KernelResult.Success)
+                if (result != KernelResult.Success)
                 {
                 {
-                    SetState(OldState);
+                    SetState(oldState);
 
 
                     CleanUpForError();
                     CleanUpForError();
-                } */
-
-                mainThread.Reschedule(ThreadSchedState.Running);
+                }
 
 
                 if (result == KernelResult.Success)
                 if (result == KernelResult.Success)
                 {
                 {
@@ -760,7 +721,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
         {
         {
             if (State != newState)
             if (State != newState)
             {
             {
-                State     = newState;
+                State = newState;
                 _signaled = true;
                 _signaled = true;
 
 
                 Signal();
                 Signal();
@@ -769,23 +730,23 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 
 
         public KernelResult InitializeThread(
         public KernelResult InitializeThread(
             KThread thread,
             KThread thread,
-            ulong   entrypoint,
-            ulong   argsPtr,
-            ulong   stackTop,
-            int     priority,
-            int     cpuCore)
+            ulong entrypoint,
+            ulong argsPtr,
+            ulong stackTop,
+            int priority,
+            int cpuCore)
         {
         {
             lock (_processLock)
             lock (_processLock)
             {
             {
-                return thread.Initialize(entrypoint, argsPtr, stackTop, priority, cpuCore, this);
+                return thread.Initialize(entrypoint, argsPtr, stackTop, priority, cpuCore, this, ThreadType.User, null);
             }
             }
         }
         }
 
 
         public void SubscribeThreadEventHandlers(ARMeilleure.State.ExecutionContext context)
         public void SubscribeThreadEventHandlers(ARMeilleure.State.ExecutionContext context)
         {
         {
-            context.Interrupt      += InterruptHandler;
+            context.Interrupt += InterruptHandler;
             context.SupervisorCall += KernelContext.SyscallHandler.SvcCall;
             context.SupervisorCall += KernelContext.SyscallHandler.SvcCall;
-            context.Undefined      += UndefinedInstructionHandler;
+            context.Undefined += UndefinedInstructionHandler;
         }
         }
 
 
         private void InterruptHandler(object sender, EventArgs e)
         private void InterruptHandler(object sender, EventArgs e)
@@ -910,8 +871,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
             {
             {
                 if (State >= ProcessState.Started)
                 if (State >= ProcessState.Started)
                 {
                 {
-                    if (State == ProcessState.Started  ||
-                        State == ProcessState.Crashed  ||
+                    if (State == ProcessState.Started ||
+                        State == ProcessState.Crashed ||
                         State == ProcessState.Attached ||
                         State == ProcessState.Attached ||
                         State == ProcessState.DebugSuspended)
                         State == ProcessState.DebugSuspended)
                     {
                     {
@@ -1072,23 +1033,25 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
             return result;
             return result;
         }
         }
 
 
-        private void InitializeMemoryManager(AddressSpaceType addrSpaceType, MemoryRegion memRegion)
+        private void InitializeMemoryManager(ProcessCreationFlags flags)
         {
         {
-            int addrSpaceBits = addrSpaceType switch
+            int addrSpaceBits = (flags & ProcessCreationFlags.AddressSpaceMask) switch
             {
             {
-                AddressSpaceType.Addr32Bits => 32,
-                AddressSpaceType.Addr36Bits => 36,
-                AddressSpaceType.Addr32BitsNoMap => 32,
-                AddressSpaceType.Addr39Bits => 39,
-                _ => throw new ArgumentException(nameof(addrSpaceType))
+                ProcessCreationFlags.AddressSpace32Bit => 32,
+                ProcessCreationFlags.AddressSpace64BitDeprecated => 36,
+                ProcessCreationFlags.AddressSpace32BitWithoutAlias => 32,
+                ProcessCreationFlags.AddressSpace64Bit => 39,
+                _ => 39
             };
             };
 
 
-            CpuMemory = new MemoryManager(KernelContext.Memory, 1UL << addrSpaceBits, InvalidAccessHandler);
-            CpuContext = new CpuContext(CpuMemory);
+            Context = _contextFactory.Create(KernelContext.Memory, 1UL << addrSpaceBits, InvalidAccessHandler);
 
 
             // TODO: This should eventually be removed.
             // TODO: This should eventually be removed.
             // The GPU shouldn't depend on the CPU memory manager at all.
             // The GPU shouldn't depend on the CPU memory manager at all.
-            KernelContext.Device.Gpu.SetVmm(CpuMemory);
+            if (flags.HasFlag(ProcessCreationFlags.IsApplication))
+            {
+                KernelContext.Device.Gpu.SetVmm((MemoryManager)CpuMemory);
+            }
 
 
             MemoryManager = new KMemoryManager(KernelContext, CpuMemory);
             MemoryManager = new KMemoryManager(KernelContext, CpuMemory);
         }
         }
@@ -1109,9 +1072,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
             throw new UndefinedInstructionException(e.Address, e.OpCode);
             throw new UndefinedInstructionException(e.Address, e.OpCode);
         }
         }
 
 
-        protected override void Destroy()
-        {
-            CpuMemory.Dispose();
-        }
+        protected override void Destroy() => Context.Dispose();
     }
     }
 }
 }

+ 14 - 13
Ryujinx.HLE/HOS/Kernel/Process/KProcessCapabilities.cs

@@ -2,6 +2,7 @@ using Ryujinx.Common;
 using Ryujinx.HLE.HOS.Kernel.Common;
 using Ryujinx.HLE.HOS.Kernel.Common;
 using Ryujinx.HLE.HOS.Kernel.Memory;
 using Ryujinx.HLE.HOS.Kernel.Memory;
 using Ryujinx.HLE.HOS.Kernel.Threading;
 using Ryujinx.HLE.HOS.Kernel.Threading;
+using System;
 
 
 namespace Ryujinx.HLE.HOS.Kernel.Process
 namespace Ryujinx.HLE.HOS.Kernel.Process
 {
 {
@@ -24,29 +25,29 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
             IrqAccessMask = new byte[0x80];
             IrqAccessMask = new byte[0x80];
         }
         }
 
 
-        public KernelResult InitializeForKernel(int[] caps, KMemoryManager memoryManager)
+        public KernelResult InitializeForKernel(ReadOnlySpan<int> capabilities, KMemoryManager memoryManager)
         {
         {
             AllowedCpuCoresMask    = 0xf;
             AllowedCpuCoresMask    = 0xf;
             AllowedThreadPriosMask = -1;
             AllowedThreadPriosMask = -1;
             DebuggingFlags        &= ~3;
             DebuggingFlags        &= ~3;
             KernelReleaseVersion   = KProcess.KernelVersionPacked;
             KernelReleaseVersion   = KProcess.KernelVersionPacked;
 
 
-            return Parse(caps, memoryManager);
+            return Parse(capabilities, memoryManager);
         }
         }
 
 
-        public KernelResult InitializeForUser(int[] caps, KMemoryManager memoryManager)
+        public KernelResult InitializeForUser(ReadOnlySpan<int> capabilities, KMemoryManager memoryManager)
         {
         {
-            return Parse(caps, memoryManager);
+            return Parse(capabilities, memoryManager);
         }
         }
 
 
-        private KernelResult Parse(int[] caps, KMemoryManager memoryManager)
+        private KernelResult Parse(ReadOnlySpan<int> capabilities, KMemoryManager memoryManager)
         {
         {
             int mask0 = 0;
             int mask0 = 0;
             int mask1 = 0;
             int mask1 = 0;
 
 
-            for (int index = 0; index < caps.Length; index++)
+            for (int index = 0; index < capabilities.Length; index++)
             {
             {
-                int cap = caps[index];
+                int cap = capabilities[index];
 
 
                 if (((cap + 1) & ~cap) != 0x40)
                 if (((cap + 1) & ~cap) != 0x40)
                 {
                 {
@@ -59,14 +60,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                 }
                 }
                 else
                 else
                 {
                 {
-                    if ((uint)index + 1 >= caps.Length)
+                    if ((uint)index + 1 >= capabilities.Length)
                     {
                     {
                         return KernelResult.InvalidCombination;
                         return KernelResult.InvalidCombination;
                     }
                     }
 
 
                     int prevCap = cap;
                     int prevCap = cap;
 
 
-                    cap = caps[++index];
+                    cap = capabilities[++index];
 
 
                     if (((cap + 1) & ~cap) != 0x40)
                     if (((cap + 1) & ~cap) != 0x40)
                     {
                     {
@@ -91,9 +92,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                         return KernelResult.InvalidAddress;
                         return KernelResult.InvalidAddress;
                     }
                     }
 
 
-                    MemoryPermission perm = (prevCap >> 31) != 0
-                        ? MemoryPermission.Read
-                        : MemoryPermission.ReadAndWrite;
+                    KMemoryPermission perm = (prevCap >> 31) != 0
+                        ? KMemoryPermission.Read
+                        : KMemoryPermission.ReadAndWrite;
 
 
                     KernelResult result;
                     KernelResult result;
 
 
@@ -216,7 +217,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
                 {
                 {
                     long address = ((long)(uint)cap << 4) & 0xffffff000;
                     long address = ((long)(uint)cap << 4) & 0xffffff000;
 
 
-                    memoryManager.MapIoMemory(address, KMemoryManager.PageSize, MemoryPermission.ReadAndWrite);
+                    memoryManager.MapIoMemory(address, KMemoryManager.PageSize, KMemoryPermission.ReadAndWrite);
 
 
                     break;
                     break;
                 }
                 }

+ 25 - 0
Ryujinx.HLE/HOS/Kernel/Process/ProcessContext.cs

@@ -0,0 +1,25 @@
+using ARMeilleure.State;
+using Ryujinx.Memory;
+using System;
+
+namespace Ryujinx.HLE.HOS.Kernel.Process
+{
+    class ProcessContext : IProcessContext
+    {
+        public IVirtualMemoryManager AddressSpace { get; }
+
+        public ProcessContext(IVirtualMemoryManager asManager)
+        {
+            AddressSpace = asManager;
+        }
+
+        public void Execute(ExecutionContext context, ulong codeAddress)
+        {
+            throw new NotSupportedException();
+        }
+
+        public void Dispose()
+        {
+        }
+    }
+}

+ 13 - 0
Ryujinx.HLE/HOS/Kernel/Process/ProcessContextFactory.cs

@@ -0,0 +1,13 @@
+using Ryujinx.Cpu;
+using Ryujinx.Memory;
+
+namespace Ryujinx.HLE.HOS.Kernel.Process
+{
+    class ProcessContextFactory : IProcessContextFactory
+    {
+        public IProcessContext Create(MemoryBlock backingMemory, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler)
+        {
+            return new ProcessContext(new AddressSpaceManager(backingMemory, addressSpaceSize));
+        }
+    }
+}

+ 38 - 0
Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationFlags.cs

@@ -0,0 +1,38 @@
+namespace Ryujinx.HLE.HOS.Kernel.Process
+{
+    enum ProcessCreationFlags
+    {
+        Is64Bit = 1 << 0,
+
+        AddressSpaceShift = 1,
+        AddressSpace32Bit = 0 << AddressSpaceShift,
+        AddressSpace64BitDeprecated = 1 << AddressSpaceShift,
+        AddressSpace32BitWithoutAlias = 2 << AddressSpaceShift,
+        AddressSpace64Bit = 3 << AddressSpaceShift,
+        AddressSpaceMask = 7 << AddressSpaceShift,
+
+        EnableDebug = 1 << 4,
+        EnableAslr = 1 << 5,
+        IsApplication = 1 << 6,
+        DeprecatedUseSecureMemory = 1 << 7,
+
+        PoolPartitionShift = 7,
+        PoolPartitionApplication = 0 << PoolPartitionShift,
+        PoolPartitionApplet = 1 << PoolPartitionShift,
+        PoolPartitionSystem = 2 << PoolPartitionShift,
+        PoolPartitionSystemNonSecure = 3 << PoolPartitionShift,
+        PoolPartitionMask = 0xf << PoolPartitionShift,
+
+        OptimizeMemoryAllocation = 1 << 11,
+
+        All =
+            Is64Bit |
+            AddressSpaceMask |
+            EnableDebug |
+            EnableAslr |
+            IsApplication |
+            DeprecatedUseSecureMemory |
+            PoolPartitionMask |
+            OptimizeMemoryAllocation
+    }
+}

+ 23 - 23
Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationInfo.cs

@@ -2,36 +2,36 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
 {
 {
     struct ProcessCreationInfo
     struct ProcessCreationInfo
     {
     {
-        public string Name { get; private set; }
+        public string Name { get; }
 
 
-        public int   Version { get; private set; }
-        public ulong TitleId  { get; private set; }
+        public int Version { get; }
+        public ulong TitleId { get; }
 
 
-        public ulong CodeAddress    { get; private set; }
-        public int   CodePagesCount { get; private set; }
+        public ulong CodeAddress { get; }
+        public int CodePagesCount { get; }
 
 
-        public int MmuFlags                 { get; private set; }
-        public int ResourceLimitHandle      { get; private set; }
-        public int PersonalMmHeapPagesCount { get; private set; }
+        public ProcessCreationFlags Flags { get; }
+        public int ResourceLimitHandle { get; }
+        public int SystemResourcePagesCount { get; }
 
 
         public ProcessCreationInfo(
         public ProcessCreationInfo(
             string name,
             string name,
-            int    category,
-            ulong  titleId,
-            ulong  codeAddress,
-            int    codePagesCount,
-            int    mmuFlags,
-            int    resourceLimitHandle,
-            int    personalMmHeapPagesCount)
+            int version,
+            ulong titleId,
+            ulong codeAddress,
+            int codePagesCount,
+            ProcessCreationFlags flags,
+            int resourceLimitHandle,
+            int systemResourcePagesCount)
         {
         {
-            Name                     = name;
-            Version                  = category;
-            TitleId                  = titleId;
-            CodeAddress              = codeAddress;
-            CodePagesCount           = codePagesCount;
-            MmuFlags                 = mmuFlags;
-            ResourceLimitHandle      = resourceLimitHandle;
-            PersonalMmHeapPagesCount = personalMmHeapPagesCount;
+            Name = name;
+            Version = version;
+            TitleId = titleId;
+            CodeAddress = codeAddress;
+            CodePagesCount = codePagesCount;
+            Flags = flags;
+            ResourceLimitHandle = resourceLimitHandle;
+            SystemResourcePagesCount = systemResourcePagesCount;
         }
         }
     }
     }
 }
 }

+ 184 - 89
Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs

@@ -7,124 +7,223 @@ using Ryujinx.HLE.HOS.Kernel.Ipc;
 using Ryujinx.HLE.HOS.Kernel.Memory;
 using Ryujinx.HLE.HOS.Kernel.Memory;
 using Ryujinx.HLE.HOS.Kernel.Process;
 using Ryujinx.HLE.HOS.Kernel.Process;
 using Ryujinx.HLE.HOS.Kernel.Threading;
 using Ryujinx.HLE.HOS.Kernel.Threading;
+using Ryujinx.Memory;
 using System;
 using System;
+using System.Threading;
 
 
 namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
 namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
 {
 {
     class Syscall
     class Syscall
     {
     {
-        private readonly Switch _device;
         private readonly KernelContext _context;
         private readonly KernelContext _context;
 
 
-        public Syscall(Switch device, KernelContext context)
+        public Syscall(KernelContext context)
         {
         {
-            _device = device;
             _context = context;
             _context = context;
         }
         }
 
 
-        // IPC
+        // Process
 
 
-        public KernelResult ConnectToNamedPort(ulong namePtr, out int handle)
+        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 KernelResult CreateProcess(
+            ProcessCreationInfo info,
+            ReadOnlySpan<int> capabilities,
+            out int handle,
+            IProcessContextFactory contextFactory,
+            ThreadStart customThreadStart = null)
         {
         {
             handle = 0;
             handle = 0;
 
 
-            if (!KernelTransfer.UserToKernelString(_context, namePtr, 12, out string name))
+            if ((info.Flags & ~ProcessCreationFlags.All) != 0)
             {
             {
-                return KernelResult.UserCopyFailed;
+                return KernelResult.InvalidEnumValue;
             }
             }
 
 
-            if (name.Length > 11)
+            // TODO: Address space check.
+
+            if ((info.Flags & ProcessCreationFlags.PoolPartitionMask) > ProcessCreationFlags.PoolPartitionSystemNonSecure)
             {
             {
-                return KernelResult.MaximumExceeded;
+                return KernelResult.InvalidEnumValue;
             }
             }
 
 
-            KAutoObject autoObj = KAutoObject.FindNamedObject(_context, name);
+            if ((info.CodeAddress & 0x1fffff) != 0)
+            {
+                return KernelResult.InvalidAddress;
+            }
 
 
-            if (!(autoObj is KClientPort clientPort))
+            if (info.CodePagesCount < 0 || info.SystemResourcePagesCount < 0)
             {
             {
-                return KernelResult.NotFound;
+                return KernelResult.InvalidSize;
             }
             }
 
 
-            KProcess currentProcess = _context.Scheduler.GetCurrentProcess();
+            if (info.Flags.HasFlag(ProcessCreationFlags.OptimizeMemoryAllocation) &&
+                !info.Flags.HasFlag(ProcessCreationFlags.IsApplication))
+            {
+                return KernelResult.InvalidThread;
+            }
 
 
-            KernelResult result = currentProcess.HandleTable.ReserveHandle(out handle);
+            KHandleTable handleTable = _context.Scheduler.GetCurrentProcess().HandleTable;
 
 
-            if (result != KernelResult.Success)
+            KProcess process = new KProcess(_context);
+
+            using var _ = new OnScopeExit(process.DecrementReferenceCount);
+
+            KResourceLimit resourceLimit;
+
+            if (info.ResourceLimitHandle != 0)
             {
             {
-                return result;
+                resourceLimit = handleTable.GetObject<KResourceLimit>(info.ResourceLimitHandle);
+
+                if (resourceLimit == null)
+                {
+                    return KernelResult.InvalidHandle;
+                }
+            }
+            else
+            {
+                resourceLimit = _context.ResourceLimit;
             }
             }
 
 
-            result = clientPort.Connect(out KClientSession clientSession);
+            MemoryRegion memRegion = (info.Flags & ProcessCreationFlags.PoolPartitionMask) switch
+            {
+                ProcessCreationFlags.PoolPartitionApplication => MemoryRegion.Application,
+                ProcessCreationFlags.PoolPartitionApplet => MemoryRegion.Applet,
+                ProcessCreationFlags.PoolPartitionSystem => MemoryRegion.Service,
+                ProcessCreationFlags.PoolPartitionSystemNonSecure => MemoryRegion.NvServices,
+                _ => MemoryRegion.NvServices
+            };
+
+            KernelResult result = process.Initialize(
+                info,
+                capabilities,
+                resourceLimit,
+                memRegion,
+                contextFactory,
+                customThreadStart);
 
 
             if (result != KernelResult.Success)
             if (result != KernelResult.Success)
             {
             {
-                currentProcess.HandleTable.CancelHandleReservation(handle);
-
                 return result;
                 return result;
             }
             }
 
 
-            currentProcess.HandleTable.SetReservedHandleObj(handle, clientSession);
-
-            clientSession.DecrementReferenceCount();
+            _context.Processes.TryAdd(process.Pid, process);
 
 
-            return result;
+            return handleTable.GenerateHandle(process, out handle);
         }
         }
 
 
-        public KernelResult SendSyncRequestHLE(int handle)
+        public KernelResult StartProcess(int handle, int priority, int cpuCore, ulong mainThreadStackSize)
         {
         {
-            KProcess process = _context.Scheduler.GetCurrentProcess();
+            KProcess process = _context.Scheduler.GetCurrentProcess().HandleTable.GetObject<KProcess>(handle);
 
 
-            KClientSession clientSession = process.HandleTable.GetObject<KClientSession>(handle);
+            if (process == null)
+            {
+                return KernelResult.InvalidHandle;
+            }
 
 
-            if (clientSession == null || clientSession.Service == null)
+            if ((uint)cpuCore >= KScheduler.CpuCoresCount || !process.IsCpuCoreAllowed(cpuCore))
             {
             {
-                return SendSyncRequest(handle);
+                return KernelResult.InvalidCpuCore;
+            }
+
+            if ((uint)priority >= KScheduler.PrioritiesCount || !process.IsPriorityAllowed(priority))
+            {
+                return KernelResult.InvalidPriority;
+            }
+
+            process.DefaultCpuCore = cpuCore;
+
+            KernelResult result = process.Start(priority, mainThreadStackSize);
+
+            if (result != KernelResult.Success)
+            {
+                return result;
             }
             }
 
 
-            return SendSyncRequestWithUserBufferHLE((ulong)_context.Scheduler.GetCurrentThread().Context.Tpidr, 0x100, handle);
+            process.IncrementReferenceCount();
+
+            return KernelResult.Success;
         }
         }
 
 
-        public KernelResult SendSyncRequestWithUserBufferHLE(ulong messagePtr, ulong messageSize, int handle)
+        // IPC
+
+        public KernelResult ConnectToNamedPort(ulong namePtr, out int handle)
         {
         {
-            KProcess process = _context.Scheduler.GetCurrentProcess();
+            handle = 0;
 
 
-            byte[] messageData = new byte[messageSize];
+            if (!KernelTransfer.UserToKernelString(_context, namePtr, 12, out string name))
+            {
+                return KernelResult.UserCopyFailed;
+            }
 
 
-            process.CpuMemory.Read(messagePtr, messageData);
+            return ConnectToNamedPort(name, out handle);
+        }
 
 
-            KClientSession clientSession = process.HandleTable.GetObject<KClientSession>(handle);
+        public KernelResult ConnectToNamedPort(string name, out int handle)
+        {
+            handle = 0;
 
 
-            if (clientSession == null || clientSession.Service == null)
+            if (name.Length > 11)
             {
             {
-                return SendSyncRequestWithUserBuffer(messagePtr, messageSize, handle);
+                return KernelResult.MaximumExceeded;
             }
             }
 
 
-            if (clientSession != null)
-            {
-                _context.CriticalSection.Enter();
+            KAutoObject autoObj = KAutoObject.FindNamedObject(_context, name);
 
 
-                KThread currentThread = _context.Scheduler.GetCurrentThread();
+            if (!(autoObj is KClientPort clientPort))
+            {
+                return KernelResult.NotFound;
+            }
 
 
-                currentThread.SignaledObj = null;
-                currentThread.ObjSyncResult = KernelResult.Success;
+            KProcess currentProcess = _context.Scheduler.GetCurrentProcess();
 
 
-                currentThread.Reschedule(ThreadSchedState.Paused);
+            KernelResult result = currentProcess.HandleTable.ReserveHandle(out handle);
 
 
-                clientSession.Service.Server.PushMessage(_device, currentThread, clientSession, messagePtr, messageSize);
+            if (result != KernelResult.Success)
+            {
+                return result;
+            }
 
 
-                _context.CriticalSection.Leave();
+            result = clientPort.Connect(out KClientSession clientSession);
 
 
-                return currentThread.ObjSyncResult;
-            }
-            else
+            if (result != KernelResult.Success)
             {
             {
-                Logger.Warning?.Print(LogClass.KernelSvc, $"Invalid session handle 0x{handle:x8}!");
+                currentProcess.HandleTable.CancelHandleReservation(handle);
 
 
-                return KernelResult.InvalidHandle;
+                return result;
             }
             }
+
+            currentProcess.HandleTable.SetReservedHandleObj(handle, clientSession);
+
+            clientSession.DecrementReferenceCount();
+
+            return result;
         }
         }
 
 
-        private KernelResult SendSyncRequest(int handle)
+        public KernelResult SendSyncRequest(int handle)
         {
         {
             KProcess currentProcess = _context.Scheduler.GetCurrentProcess();
             KProcess currentProcess = _context.Scheduler.GetCurrentProcess();
 
 
@@ -407,9 +506,18 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
                 return KernelResult.UserCopyFailed;
                 return KernelResult.UserCopyFailed;
             }
             }
 
 
-            KSynchronizationObject[] syncObjs = new KSynchronizationObject[handlesCount];
+            return ReplyAndReceive(handles, replyTargetHandle, timeout, out handleIndex);
+        }
 
 
-            for (int index = 0; index < handlesCount; index++)
+        public KernelResult ReplyAndReceive(ReadOnlySpan<int> handles, int replyTargetHandle, long timeout, out int handleIndex)
+        {
+            handleIndex = 0;
+
+            KProcess currentProcess = _context.Scheduler.GetCurrentProcess();
+
+            KSynchronizationObject[] syncObjs = new KSynchronizationObject[handles.Length];
+
+            for (int index = 0; index < handles.Length; index++)
             {
             {
                 KSynchronizationObject obj = currentProcess.HandleTable.GetObject<KSynchronizationObject>(handles[index]);
                 KSynchronizationObject obj = currentProcess.HandleTable.GetObject<KSynchronizationObject>(handles[index]);
 
 
@@ -601,7 +709,19 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
                 return KernelResult.UserCopyFailed;
                 return KernelResult.UserCopyFailed;
             }
             }
 
 
-            if (maxSessions < 0 || name.Length > 11)
+            if (name.Length > 11)
+            {
+                return KernelResult.MaximumExceeded;
+            }
+
+            return ManageNamedPort(name, maxSessions, out handle);
+        }
+
+        public KernelResult ManageNamedPort(string name, int maxSessions, out int handle)
+        {
+            handle = 0;
+
+            if (maxSessions < 0)
             {
             {
                 return KernelResult.MaximumExceeded;
                 return KernelResult.MaximumExceeded;
             }
             }
@@ -826,7 +946,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
             return KernelResult.Success;
             return KernelResult.Success;
         }
         }
 
 
-        public KernelResult MapSharedMemory(int handle, ulong address, ulong size, MemoryPermission permission)
+        public KernelResult MapSharedMemory(int handle, ulong address, ulong size, KMemoryPermission permission)
         {
         {
             if (!PageAligned(address))
             if (!PageAligned(address))
             {
             {
@@ -843,7 +963,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
                 return KernelResult.InvalidMemState;
                 return KernelResult.InvalidMemState;
             }
             }
 
 
-            if ((permission | MemoryPermission.Write) != MemoryPermission.ReadAndWrite)
+            if ((permission | KMemoryPermission.Write) != KMemoryPermission.ReadAndWrite)
             {
             {
                 return KernelResult.InvalidPermission;
                 return KernelResult.InvalidPermission;
             }
             }
@@ -912,7 +1032,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
                 currentProcess);
                 currentProcess);
         }
         }
 
 
-        public KernelResult CreateTransferMemory(ulong address, ulong size, MemoryPermission permission, out int handle)
+        public KernelResult CreateTransferMemory(ulong address, ulong size, KMemoryPermission permission, out int handle)
         {
         {
             handle = 0;
             handle = 0;
 
 
@@ -931,7 +1051,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
                 return KernelResult.InvalidMemState;
                 return KernelResult.InvalidMemState;
             }
             }
 
 
-            if (permission > MemoryPermission.ReadAndWrite || permission == MemoryPermission.Write)
+            if (permission > KMemoryPermission.ReadAndWrite || permission == KMemoryPermission.Write)
             {
             {
                 return KernelResult.InvalidPermission;
                 return KernelResult.InvalidPermission;
             }
             }
@@ -1119,7 +1239,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
             return targetProcess.MemoryManager.UnmapProcessCodeMemory(dst, src, size);
             return targetProcess.MemoryManager.UnmapProcessCodeMemory(dst, src, size);
         }
         }
 
 
-        public KernelResult SetProcessMemoryPermission(int handle, ulong src, ulong size, MemoryPermission permission)
+        public KernelResult SetProcessMemoryPermission(int handle, ulong src, ulong size, KMemoryPermission permission)
         {
         {
             if (!PageAligned(src))
             if (!PageAligned(src))
             {
             {
@@ -1131,10 +1251,10 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
                 return KernelResult.InvalidSize;
                 return KernelResult.InvalidSize;
             }
             }
 
 
-            if (permission != MemoryPermission.None &&
-                permission != MemoryPermission.Read &&
-                permission != MemoryPermission.ReadAndWrite &&
-                permission != MemoryPermission.ReadAndExecute)
+            if (permission != KMemoryPermission.None &&
+                permission != KMemoryPermission.Read &&
+                permission != KMemoryPermission.ReadAndWrite &&
+                permission != KMemoryPermission.ReadAndExecute)
             {
             {
                 return KernelResult.InvalidPermission;
                 return KernelResult.InvalidPermission;
             }
             }
@@ -1282,31 +1402,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
             return _context.Scheduler.GetCurrentThread().Context.CntpctEl0;
             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)
         public void Break(ulong reason)
         {
         {
             KThread currentThread = _context.Scheduler.GetCurrentThread();
             KThread currentThread = _context.Scheduler.GetCurrentThread();
@@ -1997,7 +2092,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
                 return KernelResult.InvalidThread;
                 return KernelResult.InvalidThread;
             }
             }
 
 
-            MemoryManager memory = currentProcess.CpuMemory;
+            IVirtualMemoryManager memory = currentProcess.CpuMemory;
 
 
             memory.Write(address + 0x0, thread.Context.GetX(0));
             memory.Write(address + 0x0, thread.Context.GetX(0));
             memory.Write(address + 0x8, thread.Context.GetX(1));
             memory.Write(address + 0x8, thread.Context.GetX(1));

+ 5 - 5
Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs

@@ -22,12 +22,12 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
 
 
         public KernelResult SendSyncRequest32([R(0)] int handle)
         public KernelResult SendSyncRequest32([R(0)] int handle)
         {
         {
-            return _syscall.SendSyncRequestHLE(handle);
+            return _syscall.SendSyncRequest(handle);
         }
         }
 
 
         public KernelResult SendSyncRequestWithUserBuffer32([R(0)] uint messagePtr, [R(1)] uint messageSize, [R(2)] int handle)
         public KernelResult SendSyncRequestWithUserBuffer32([R(0)] uint messagePtr, [R(1)] uint messageSize, [R(2)] int handle)
         {
         {
-            return _syscall.SendSyncRequestWithUserBufferHLE(messagePtr, messageSize, handle);
+            return _syscall.SendSyncRequestWithUserBuffer(messagePtr, messageSize, handle);
         }
         }
 
 
         public KernelResult CreateSession32(
         public KernelResult CreateSession32(
@@ -116,7 +116,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
             return result;
             return result;
         }
         }
 
 
-        public KernelResult MapSharedMemory32([R(0)] int handle, [R(1)] uint address, [R(2)] uint size, [R(3)] MemoryPermission permission)
+        public KernelResult MapSharedMemory32([R(0)] int handle, [R(1)] uint address, [R(2)] uint size, [R(3)] KMemoryPermission permission)
         {
         {
             return _syscall.MapSharedMemory(handle, address, size, permission);
             return _syscall.MapSharedMemory(handle, address, size, permission);
         }
         }
@@ -129,7 +129,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
         public KernelResult CreateTransferMemory32(
         public KernelResult CreateTransferMemory32(
             [R(1)] uint address,
             [R(1)] uint address,
             [R(2)] uint size,
             [R(2)] uint size,
-            [R(3)] MemoryPermission permission,
+            [R(3)] KMemoryPermission permission,
             [R(1)] out int handle)
             [R(1)] out int handle)
         {
         {
             return _syscall.CreateTransferMemory(address, size, permission, out handle);
             return _syscall.CreateTransferMemory(address, size, permission, out handle);
@@ -169,7 +169,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
             [R(2)] uint srcLow,
             [R(2)] uint srcLow,
             [R(3)] uint srcHigh,
             [R(3)] uint srcHigh,
             [R(4)] uint sizeHigh,
             [R(4)] uint sizeHigh,
-            [R(5)] MemoryPermission permission)
+            [R(5)] KMemoryPermission permission)
         {
         {
             ulong src = srcLow | ((ulong)srcHigh << 32);
             ulong src = srcLow | ((ulong)srcHigh << 32);
             ulong size = sizeLow | ((ulong)sizeHigh << 32);
             ulong size = sizeLow | ((ulong)sizeHigh << 32);

+ 5 - 5
Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs

@@ -22,12 +22,12 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
 
 
         public KernelResult SendSyncRequest64([R(0)] int handle)
         public KernelResult SendSyncRequest64([R(0)] int handle)
         {
         {
-            return _syscall.SendSyncRequestHLE(handle);
+            return _syscall.SendSyncRequest(handle);
         }
         }
 
 
         public KernelResult SendSyncRequestWithUserBuffer64([R(0)] ulong messagePtr, [R(1)] ulong messageSize, [R(2)] int handle)
         public KernelResult SendSyncRequestWithUserBuffer64([R(0)] ulong messagePtr, [R(1)] ulong messageSize, [R(2)] int handle)
         {
         {
-            return _syscall.SendSyncRequestWithUserBufferHLE(messagePtr, messageSize, handle);
+            return _syscall.SendSyncRequestWithUserBuffer(messagePtr, messageSize, handle);
         }
         }
 
 
         public KernelResult SendAsyncRequestWithUserBuffer64(
         public KernelResult SendAsyncRequestWithUserBuffer64(
@@ -133,7 +133,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
             return _syscall.QueryMemory(infoPtr, position, out 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)
+        public KernelResult MapSharedMemory64([R(0)] int handle, [R(1)] ulong address, [R(2)] ulong size, [R(3)] KMemoryPermission permission)
         {
         {
             return _syscall.MapSharedMemory(handle, address, size, permission);
             return _syscall.MapSharedMemory(handle, address, size, permission);
         }
         }
@@ -146,7 +146,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
         public KernelResult CreateTransferMemory64(
         public KernelResult CreateTransferMemory64(
             [R(1)] ulong address,
             [R(1)] ulong address,
             [R(2)] ulong size,
             [R(2)] ulong size,
-            [R(3)] MemoryPermission permission,
+            [R(3)] KMemoryPermission permission,
             [R(1)] out int handle)
             [R(1)] out int handle)
         {
         {
             return _syscall.CreateTransferMemory(address, size, permission, out handle);
             return _syscall.CreateTransferMemory(address, size, permission, out handle);
@@ -172,7 +172,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
             return _syscall.UnmapProcessCodeMemory(handle, dst, src, 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)
+        public KernelResult SetProcessMemoryPermission64([R(0)] int handle, [R(1)] ulong src, [R(2)] ulong size, [R(3)] KMemoryPermission permission)
         {
         {
             return _syscall.SetProcessMemoryPermission(handle, src, size, permission);
             return _syscall.SetProcessMemoryPermission(handle, src, size, permission);
         }
         }

+ 2 - 0
Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs

@@ -229,6 +229,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
 
 
             KProcess dummyProcess = new KProcess(_context);
             KProcess dummyProcess = new KProcess(_context);
 
 
+            dummyProcess.HandleTable.Initialize(1024);
+
             KThread dummyThread = new KThread(_context);
             KThread dummyThread = new KThread(_context);
 
 
             dummyThread.Initialize(0, 0, 0, 44, 0, dummyProcess, ThreadType.Dummy);
             dummyThread.Initialize(0, 0, 0, 44, 0, dummyProcess, ThreadType.Dummy);

+ 50 - 40
Ryujinx.HLE/HOS/Kernel/Threading/KThread.cs

@@ -31,6 +31,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
         public ulong CondVarAddress { get; set; }
         public ulong CondVarAddress { get; set; }
 
 
         private ulong _entrypoint;
         private ulong _entrypoint;
+        private ThreadStart _customThreadStart;
 
 
         public ulong MutexAddress { get; set; }
         public ulong MutexAddress { get; set; }
 
 
@@ -48,12 +49,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
 
 
         public LinkedListNode<KThread>[] SiblingsPerCore { get; private set; }
         public LinkedListNode<KThread>[] SiblingsPerCore { get; private set; }
 
 
-        public LinkedList<KThread>     Withholder     { get; set; }
+        public LinkedList<KThread> Withholder { get; set; }
         public LinkedListNode<KThread> WithholderNode { get; set; }
         public LinkedListNode<KThread> WithholderNode { get; set; }
 
 
         public LinkedListNode<KThread> ProcessListNode { get; set; }
         public LinkedListNode<KThread> ProcessListNode { get; set; }
 
 
-        private LinkedList<KThread>     _mutexWaiters;
+        private LinkedList<KThread> _mutexWaiters;
         private LinkedListNode<KThread> _mutexWaiterNode;
         private LinkedListNode<KThread> _mutexWaiterNode;
 
 
         public KThread MutexOwner { get; private set; }
         public KThread MutexOwner { get; private set; }
@@ -65,24 +66,28 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
         public KernelResult ObjSyncResult { get; set; }
         public KernelResult ObjSyncResult { get; set; }
 
 
         public int DynamicPriority { get; set; }
         public int DynamicPriority { get; set; }
-        public int CurrentCore     { get; set; }
-        public int BasePriority    { get; set; }
-        public int PreferredCore   { get; set; }
+        public int CurrentCore { get; set; }
+        public int BasePriority { get; set; }
+        public int PreferredCore { get; set; }
 
 
         private long _affinityMaskOverride;
         private long _affinityMaskOverride;
-        private int  _preferredCoreOverride;
+        private int _preferredCoreOverride;
 #pragma warning disable CS0649
 #pragma warning disable CS0649
-        private int  _affinityOverrideCount;
+        private int _affinityOverrideCount;
 #pragma warning restore CS0649
 #pragma warning restore CS0649
 
 
         public ThreadSchedState SchedFlags { get; private set; }
         public ThreadSchedState SchedFlags { get; private set; }
 
 
         private int _shallBeTerminated;
         private int _shallBeTerminated;
 
 
-        public bool ShallBeTerminated { get => _shallBeTerminated != 0; set => _shallBeTerminated = value ? 1 : 0; }
+        public bool ShallBeTerminated
+        {
+            get => _shallBeTerminated != 0;
+            set => _shallBeTerminated = value ? 1 : 0;
+        }
 
 
         public bool SyncCancelled { get; set; }
         public bool SyncCancelled { get; set; }
-        public bool WaitingSync   { get; set; }
+        public bool WaitingSync { get; set; }
 
 
         private bool _hasExited;
         private bool _hasExited;
         private bool _hasBeenInitialized;
         private bool _hasBeenInitialized;
@@ -98,7 +103,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
 
 
         public KThread(KernelContext context) : base(context)
         public KThread(KernelContext context) : base(context)
         {
         {
-            _scheduler      = KernelContext.Scheduler;
+            _scheduler = KernelContext.Scheduler;
             _schedulingData = KernelContext.Scheduler.SchedulingData;
             _schedulingData = KernelContext.Scheduler.SchedulingData;
 
 
             WaitSyncObjects = new KSynchronizationObject[MaxWaitSyncObjects];
             WaitSyncObjects = new KSynchronizationObject[MaxWaitSyncObjects];
@@ -110,14 +115,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
         }
         }
 
 
         public KernelResult Initialize(
         public KernelResult Initialize(
-            ulong      entrypoint,
-            ulong      argsPtr,
-            ulong      stackTop,
-            int        priority,
-            int        defaultCpuCore,
-            KProcess   owner,
-            ThreadType type = ThreadType.User,
-            ThreadStart customHostThreadStart = null)
+            ulong entrypoint,
+            ulong argsPtr,
+            ulong stackTop,
+            int priority,
+            int defaultCpuCore,
+            KProcess owner,
+            ThreadType type,
+            ThreadStart customThreadStart = null)
         {
         {
             if ((uint)type > 3)
             if ((uint)type > 3)
             {
             {
@@ -135,11 +140,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
             CurrentCore = PreferredCore;
             CurrentCore = PreferredCore;
 
 
             DynamicPriority = priority;
             DynamicPriority = priority;
-            BasePriority    = priority;
+            BasePriority = priority;
 
 
             ObjSyncResult = KernelResult.ThreadNotStarted;
             ObjSyncResult = KernelResult.ThreadNotStarted;
 
 
             _entrypoint = entrypoint;
             _entrypoint = entrypoint;
+            _customThreadStart = customThreadStart;
 
 
             if (type == ThreadType.User)
             if (type == ThreadType.User)
             {
             {
@@ -162,18 +168,18 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
                 owner.IncrementReferenceCount();
                 owner.IncrementReferenceCount();
                 owner.IncrementThreadCount();
                 owner.IncrementThreadCount();
 
 
-                is64Bits = (owner.MmuFlags & 1) != 0;
+                is64Bits = owner.Flags.HasFlag(ProcessCreationFlags.Is64Bit);
             }
             }
             else
             else
             {
             {
                 is64Bits = true;
                 is64Bits = true;
             }
             }
 
 
-            HostThread = new Thread(customHostThreadStart ?? (() => ThreadStart(entrypoint)));
+            HostThread = new Thread(ThreadStart);
 
 
             Context = CpuContext.CreateExecutionContext();
             Context = CpuContext.CreateExecutionContext();
 
 
-            bool isAarch32 = (Owner.MmuFlags & 1) == 0;
+            bool isAarch32 = !Owner.Flags.HasFlag(ProcessCreationFlags.Is64Bit);
 
 
             Context.IsAarch32 = isAarch32;
             Context.IsAarch32 = isAarch32;
 
 
@@ -189,7 +195,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
             }
             }
 
 
             Context.CntfrqEl0 = 19200000;
             Context.CntfrqEl0 = 19200000;
-            Context.Tpidr     = (long)_tlsAddress;
+            Context.Tpidr = (long)_tlsAddress;
 
 
             owner.SubscribeThreadEventHandlers(Context);
             owner.SubscribeThreadEventHandlers(Context);
 
 
@@ -249,7 +255,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
             {
             {
                 KThread currentThread = KernelContext.Scheduler.GetCurrentThread();
                 KThread currentThread = KernelContext.Scheduler.GetCurrentThread();
 
 
-                while (SchedFlags               != ThreadSchedState.TerminationPending &&
+                while (SchedFlags != ThreadSchedState.TerminationPending &&
                        currentThread.SchedFlags != ThreadSchedState.TerminationPending &&
                        currentThread.SchedFlags != ThreadSchedState.TerminationPending &&
                        !currentThread.ShallBeTerminated)
                        !currentThread.ShallBeTerminated)
                 {
                 {
@@ -351,7 +357,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
                         Context.RequestInterrupt();
                         Context.RequestInterrupt();
                     }
                     }
 
 
-                    SignaledObj   = null;
+                    SignaledObj = null;
                     ObjSyncResult = KernelResult.ThreadTerminating;
                     ObjSyncResult = KernelResult.ThreadTerminating;
 
 
                     ReleaseAndResume();
                     ReleaseAndResume();
@@ -524,7 +530,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
                     // If the candidate was scheduled after the current thread, then it's not worth it,
                     // If the candidate was scheduled after the current thread, then it's not worth it,
                     // unless the priority is higher than the current one.
                     // unless the priority is higher than the current one.
                     if (nextThreadOnCurrentQueue.LastScheduledTime >= thread.LastScheduledTime ||
                     if (nextThreadOnCurrentQueue.LastScheduledTime >= thread.LastScheduledTime ||
-                        nextThreadOnCurrentQueue.DynamicPriority    <  thread.DynamicPriority)
+                        nextThreadOnCurrentQueue.DynamicPriority < thread.DynamicPriority)
                     {
                     {
                         yield return thread;
                         yield return thread;
                     }
                     }
@@ -701,7 +707,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
             }
             }
             else
             else
             {
             {
-                SignaledObj   = null;
+                SignaledObj = null;
                 ObjSyncResult = KernelResult.Cancelled;
                 ObjSyncResult = KernelResult.Cancelled;
 
 
                 SetNewSchedFlags(ThreadSchedState.Running);
                 SetNewSchedFlags(ThreadSchedState.Running);
@@ -734,14 +740,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
             if (useOverride)
             if (useOverride)
             {
             {
                 _preferredCoreOverride = newCore;
                 _preferredCoreOverride = newCore;
-                _affinityMaskOverride  = newAffinityMask;
+                _affinityMaskOverride = newAffinityMask;
             }
             }
             else
             else
             {
             {
                 long oldAffinityMask = AffinityMask;
                 long oldAffinityMask = AffinityMask;
 
 
                 PreferredCore = newCore;
                 PreferredCore = newCore;
-                AffinityMask  = newAffinityMask;
+                AffinityMask = newAffinityMask;
 
 
                 if (oldAffinityMask != newAffinityMask)
                 if (oldAffinityMask != newAffinityMask)
                 {
                 {
@@ -783,7 +789,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
 
 
         private void CombineForcePauseFlags()
         private void CombineForcePauseFlags()
         {
         {
-            ThreadSchedState oldFlags  = SchedFlags;
+            ThreadSchedState oldFlags = SchedFlags;
             ThreadSchedState lowNibble = SchedFlags & ThreadSchedState.LowMask;
             ThreadSchedState lowNibble = SchedFlags & ThreadSchedState.LowMask;
 
 
             SchedFlags = lowNibble | _forcePauseFlags;
             SchedFlags = lowNibble | _forcePauseFlags;
@@ -1143,19 +1149,23 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
             }
             }
         }
         }
 
 
-        private void ThreadStart(ulong entrypoint)
+        private void ThreadStart()
         {
         {
-            Owner.CpuContext.Execute(Context, entrypoint);
+            KernelStatic.SetKernelContext(KernelContext);
 
 
-            ThreadExit();
-
-            Context.Dispose();
-        }
+            if (_customThreadStart != null)
+            {
+                _customThreadStart();
+            }
+            else
+            {
+                Owner.Context.Execute(Context, _entrypoint);
+            }
 
 
-        private void ThreadExit()
-        {
             KernelContext.Scheduler.ExitThread(this);
             KernelContext.Scheduler.ExitThread(this);
             KernelContext.Scheduler.RemoveThread(this);
             KernelContext.Scheduler.RemoveThread(this);
+
+            Context.Dispose();
         }
         }
 
 
         public bool IsCurrentHostThread()
         public bool IsCurrentHostThread()
@@ -1203,9 +1213,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
             // Wake up all threads that may be waiting for a mutex being held by this thread.
             // Wake up all threads that may be waiting for a mutex being held by this thread.
             foreach (KThread thread in _mutexWaiters)
             foreach (KThread thread in _mutexWaiters)
             {
             {
-                thread.MutexOwner             = null;
+                thread.MutexOwner = null;
                 thread._preferredCoreOverride = 0;
                 thread._preferredCoreOverride = 0;
-                thread.ObjSyncResult          = KernelResult.InvalidState;
+                thread.ObjSyncResult = KernelResult.InvalidState;
 
 
                 thread.ReleaseAndResume();
                 thread.ReleaseAndResume();
             }
             }

+ 18 - 12
Ryujinx.HLE/HOS/ProgramLoader.cs

@@ -36,23 +36,23 @@ namespace Ryujinx.HLE.HOS
 
 
             ulong codeAddress = codeBaseAddress + (ulong)kip.TextOffset;
             ulong codeAddress = codeBaseAddress + (ulong)kip.TextOffset;
 
 
-            int mmuFlags = 0;
+            ProcessCreationFlags flags = 0;
 
 
             if (AslrEnabled)
             if (AslrEnabled)
             {
             {
                 // TODO: Randomization.
                 // TODO: Randomization.
 
 
-                mmuFlags |= 0x20;
+                flags |= ProcessCreationFlags.EnableAslr;
             }
             }
 
 
             if (kip.Is64BitAddressSpace)
             if (kip.Is64BitAddressSpace)
             {
             {
-                mmuFlags |= (int)AddressSpaceType.Addr39Bits << 1;
+                flags |= ProcessCreationFlags.AddressSpace64Bit;
             }
             }
 
 
             if (kip.Is64Bit)
             if (kip.Is64Bit)
             {
             {
-                mmuFlags |= 1;
+                flags |= ProcessCreationFlags.Is64Bit;
             }
             }
 
 
             ProcessCreationInfo creationInfo = new ProcessCreationInfo(
             ProcessCreationInfo creationInfo = new ProcessCreationInfo(
@@ -61,7 +61,7 @@ namespace Ryujinx.HLE.HOS
                 kip.ProgramId,
                 kip.ProgramId,
                 codeAddress,
                 codeAddress,
                 codePagesCount,
                 codePagesCount,
-                mmuFlags,
+                flags,
                 0,
                 0,
                 0);
                 0);
 
 
@@ -82,12 +82,15 @@ namespace Ryujinx.HLE.HOS
 
 
             KProcess process = new KProcess(context);
             KProcess process = new KProcess(context);
 
 
+            var processContextFactory = new ArmProcessContextFactory();
+
             result = process.InitializeKip(
             result = process.InitializeKip(
                 creationInfo,
                 creationInfo,
                 kip.Capabilities,
                 kip.Capabilities,
                 pageList,
                 pageList,
                 context.ResourceLimit,
                 context.ResourceLimit,
-                memoryRegion);
+                memoryRegion,
+                processContextFactory);
 
 
             if (result != KernelResult.Success)
             if (result != KernelResult.Success)
             {
             {
@@ -183,7 +186,7 @@ namespace Ryujinx.HLE.HOS
                 metaData.Aci0.TitleId,
                 metaData.Aci0.TitleId,
                 codeStart,
                 codeStart,
                 codePagesCount,
                 codePagesCount,
-                metaData.MmuFlags,
+                (ProcessCreationFlags)metaData.ProcessFlags | ProcessCreationFlags.IsApplication,
                 0,
                 0,
                 personalMmHeapPagesCount);
                 personalMmHeapPagesCount);
 
 
@@ -217,11 +220,14 @@ namespace Ryujinx.HLE.HOS
                 return false;
                 return false;
             }
             }
 
 
+            var processContextFactory = new ArmProcessContextFactory();
+
             result = process.Initialize(
             result = process.Initialize(
                 creationInfo,
                 creationInfo,
                 metaData.Aci0.KernelAccessControl.Capabilities,
                 metaData.Aci0.KernelAccessControl.Capabilities,
                 resourceLimit,
                 resourceLimit,
-                memoryRegion);
+                memoryRegion,
+                processContextFactory);
 
 
             if (result != KernelResult.Success)
             if (result != KernelResult.Success)
             {
             {
@@ -280,7 +286,7 @@ namespace Ryujinx.HLE.HOS
 
 
             MemoryHelper.FillWithZeros(process.CpuMemory, (long)bssStart, image.BssSize);
             MemoryHelper.FillWithZeros(process.CpuMemory, (long)bssStart, image.BssSize);
 
 
-            KernelResult SetProcessMemoryPermission(ulong address, ulong size, MemoryPermission permission)
+            KernelResult SetProcessMemoryPermission(ulong address, ulong size, KMemoryPermission permission)
             {
             {
                 if (size == 0)
                 if (size == 0)
                 {
                 {
@@ -292,21 +298,21 @@ namespace Ryujinx.HLE.HOS
                 return process.MemoryManager.SetProcessMemoryPermission(address, size, permission);
                 return process.MemoryManager.SetProcessMemoryPermission(address, size, permission);
             }
             }
 
 
-            KernelResult result = SetProcessMemoryPermission(textStart, (ulong)image.Text.Length, MemoryPermission.ReadAndExecute);
+            KernelResult result = SetProcessMemoryPermission(textStart, (ulong)image.Text.Length, KMemoryPermission.ReadAndExecute);
 
 
             if (result != KernelResult.Success)
             if (result != KernelResult.Success)
             {
             {
                 return result;
                 return result;
             }
             }
 
 
-            result = SetProcessMemoryPermission(roStart, (ulong)image.Ro.Length, MemoryPermission.Read);
+            result = SetProcessMemoryPermission(roStart, (ulong)image.Ro.Length, KMemoryPermission.Read);
 
 
             if (result != KernelResult.Success)
             if (result != KernelResult.Success)
             {
             {
                 return result;
                 return result;
             }
             }
 
 
-            return SetProcessMemoryPermission(dataStart, end - dataStart, MemoryPermission.ReadAndWrite);
+            return SetProcessMemoryPermission(dataStart, end - dataStart, KMemoryPermission.ReadAndWrite);
         }
         }
     }
     }
 }
 }

+ 24 - 28
Ryujinx.HLE/HOS/ServiceCtx.cs

@@ -1,43 +1,39 @@
-using Ryujinx.Cpu;
 using Ryujinx.HLE.HOS.Ipc;
 using Ryujinx.HLE.HOS.Ipc;
-using Ryujinx.HLE.HOS.Kernel.Ipc;
 using Ryujinx.HLE.HOS.Kernel.Process;
 using Ryujinx.HLE.HOS.Kernel.Process;
 using Ryujinx.HLE.HOS.Kernel.Threading;
 using Ryujinx.HLE.HOS.Kernel.Threading;
+using Ryujinx.Memory;
 using System.IO;
 using System.IO;
 
 
 namespace Ryujinx.HLE.HOS
 namespace Ryujinx.HLE.HOS
 {
 {
     class ServiceCtx
     class ServiceCtx
     {
     {
-        public Switch         Device       { get; }
-        public KProcess       Process      { get; }
-        public MemoryManager  Memory       { get; }
-        public KThread        Thread       { get; }
-        public KClientSession Session      { get; }
-        public IpcMessage     Request      { get; }
-        public IpcMessage     Response     { get; }
-        public BinaryReader   RequestData  { get; }
-        public BinaryWriter   ResponseData { get; }
+        public Switch Device { get; }
+        public KProcess Process { get; }
+        public IVirtualMemoryManager Memory { get; }
+        public KThread Thread { get; }
+        public IpcMessage Request { get; }
+        public IpcMessage Response { get; }
+        public BinaryReader RequestData { get; }
+        public BinaryWriter ResponseData { get; }
 
 
         public ServiceCtx(
         public ServiceCtx(
-            Switch         device,
-            KProcess       process,
-            MemoryManager  memory,
-            KThread        thread,
-            KClientSession session,
-            IpcMessage     request,
-            IpcMessage     response,
-            BinaryReader   requestData,
-            BinaryWriter   responseData)
+            Switch device,
+            KProcess process,
+            IVirtualMemoryManager memory,
+            KThread thread,
+            IpcMessage request,
+            IpcMessage response,
+            BinaryReader requestData,
+            BinaryWriter responseData)
         {
         {
-            Device       = device;
-            Process      = process;
-            Memory       = memory;
-            Thread       = thread;
-            Session      = session;
-            Request      = request;
-            Response     = response;
-            RequestData  = requestData;
+            Device = device;
+            Process = process;
+            Memory = memory;
+            Thread = thread;
+            Request = request;
+            Response = response;
+            RequestData = requestData;
             ResponseData = responseData;
             ResponseData = responseData;
         }
         }
     }
     }

+ 8 - 3
Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs

@@ -4,7 +4,12 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
 {
 {
     class ISystemAppletProxy : IpcService
     class ISystemAppletProxy : IpcService
     {
     {
-        public ISystemAppletProxy() { }
+        private readonly long _pid;
+
+        public ISystemAppletProxy(long pid)
+        {
+            _pid = pid;
+        }
 
 
         [Command(0)]
         [Command(0)]
         // GetCommonStateGetter() -> object<nn::am::service::ICommonStateGetter>
         // GetCommonStateGetter() -> object<nn::am::service::ICommonStateGetter>
@@ -19,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
         // GetSelfController() -> object<nn::am::service::ISelfController>
         // GetSelfController() -> object<nn::am::service::ISelfController>
         public ResultCode GetSelfController(ServiceCtx context)
         public ResultCode GetSelfController(ServiceCtx context)
         {
         {
-            MakeObject(context, new ISelfController(context.Device.System));
+            MakeObject(context, new ISelfController(context.Device.System, _pid));
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }
@@ -28,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
         // GetWindowController() -> object<nn::am::service::IWindowController>
         // GetWindowController() -> object<nn::am::service::IWindowController>
         public ResultCode GetWindowController(ServiceCtx context)
         public ResultCode GetWindowController(ServiceCtx context)
         {
         {
-            MakeObject(context, new IWindowController());
+            MakeObject(context, new IWindowController(_pid));
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }

+ 25 - 12
Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs

@@ -18,6 +18,10 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
         private KEvent _normalOutDataEvent;
         private KEvent _normalOutDataEvent;
         private KEvent _interactiveOutDataEvent;
         private KEvent _interactiveOutDataEvent;
 
 
+        private int _stateChangedEventHandle;
+        private int _normalOutDataEventHandle;
+        private int _interactiveOutDataEventHandle;
+
         public ILibraryAppletAccessor(AppletId appletId, Horizon system)
         public ILibraryAppletAccessor(AppletId appletId, Horizon system)
         {
         {
             _stateChangedEvent       = new KEvent(system.KernelContext);
             _stateChangedEvent       = new KEvent(system.KernelContext);
@@ -32,7 +36,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
             _applet.AppletStateChanged        += OnAppletStateChanged;
             _applet.AppletStateChanged        += OnAppletStateChanged;
             _normalSession.DataAvailable      += OnNormalOutData;
             _normalSession.DataAvailable      += OnNormalOutData;
             _interactiveSession.DataAvailable += OnInteractiveOutData;
             _interactiveSession.DataAvailable += OnInteractiveOutData;
-            
+
             Logger.Info?.Print(LogClass.ServiceAm, $"Applet '{appletId}' created.");
             Logger.Info?.Print(LogClass.ServiceAm, $"Applet '{appletId}' created.");
         }
         }
 
 
@@ -55,12 +59,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
         // GetAppletStateChangedEvent() -> handle<copy>
         // GetAppletStateChangedEvent() -> handle<copy>
         public ResultCode GetAppletStateChangedEvent(ServiceCtx context)
         public ResultCode GetAppletStateChangedEvent(ServiceCtx context)
         {
         {
-            if (context.Process.HandleTable.GenerateHandle(_stateChangedEvent.ReadableEvent, out int handle) != KernelResult.Success)
+            if (_stateChangedEventHandle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(_stateChangedEvent.ReadableEvent, out _stateChangedEventHandle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_stateChangedEventHandle);
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }
@@ -69,8 +76,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
         // Start()
         // Start()
         public ResultCode Start(ServiceCtx context)
         public ResultCode Start(ServiceCtx context)
         {
         {
-            return (ResultCode)_applet.Start(_normalSession.GetConsumer(),
-                                             _interactiveSession.GetConsumer());
+            return (ResultCode)_applet.Start(_normalSession.GetConsumer(), _interactiveSession.GetConsumer());
         }
         }
 
 
         [Command(30)]
         [Command(30)]
@@ -138,12 +144,16 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
         // GetPopOutDataEvent() -> handle<copy>
         // GetPopOutDataEvent() -> handle<copy>
         public ResultCode GetPopOutDataEvent(ServiceCtx context)
         public ResultCode GetPopOutDataEvent(ServiceCtx context)
         {
         {
-            if (context.Process.HandleTable.GenerateHandle(_normalOutDataEvent.ReadableEvent, out int handle) != KernelResult.Success)
+            if (_normalOutDataEventHandle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(_normalOutDataEvent.ReadableEvent, out _normalOutDataEventHandle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
+
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_normalOutDataEventHandle);
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }
@@ -152,12 +162,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib
         // GetPopInteractiveOutDataEvent() -> handle<copy>
         // GetPopInteractiveOutDataEvent() -> handle<copy>
         public ResultCode GetPopInteractiveOutDataEvent(ServiceCtx context)
         public ResultCode GetPopInteractiveOutDataEvent(ServiceCtx context)
         {
         {
-            if (context.Process.HandleTable.GenerateHandle(_interactiveOutDataEvent.ReadableEvent, out int handle) != KernelResult.Success)
+            if (_interactiveOutDataEventHandle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(_interactiveOutDataEvent.ReadableEvent, out _interactiveOutDataEventHandle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_interactiveOutDataEventHandle);
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }

+ 18 - 10
Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs

@@ -12,7 +12,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
         private Apm.SystemManagerServer _apmSystemManagerServer;
         private Apm.SystemManagerServer _apmSystemManagerServer;
         private Lbl.LblControllerServer _lblControllerServer;
         private Lbl.LblControllerServer _lblControllerServer;
 
 
-        private bool _vrModeEnabled = false;
+        private bool _vrModeEnabled;
+        private int _messageEventHandle;
+        private int _displayResolutionChangedEventHandle;
 
 
         public ICommonStateGetter(ServiceCtx context)
         public ICommonStateGetter(ServiceCtx context)
         {
         {
@@ -25,14 +27,17 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
         // GetEventHandle() -> handle<copy>
         // GetEventHandle() -> handle<copy>
         public ResultCode GetEventHandle(ServiceCtx context)
         public ResultCode GetEventHandle(ServiceCtx context)
         {
         {
-            KEvent Event = context.Device.System.AppletState.MessageEvent;
+            KEvent messageEvent = context.Device.System.AppletState.MessageEvent;
 
 
-            if (context.Process.HandleTable.GenerateHandle(Event.ReadableEvent, out int handle) != KernelResult.Success)
+            if (_messageEventHandle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(messageEvent.ReadableEvent, out _messageEventHandle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_messageEventHandle);
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }
@@ -147,7 +152,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
                 _lblControllerServer.DisableVrMode();
                 _lblControllerServer.DisableVrMode();
             }
             }
 
 
-            // TODO: It signals an internal event of ICommonStateGetter. We have to determine where this event is used. 
+            // TODO: It signals an internal event of ICommonStateGetter. We have to determine where this event is used.
         }
         }
 
 
         [Command(60)] // 3.0.0+
         [Command(60)] // 3.0.0+
@@ -164,12 +169,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
         // GetDefaultDisplayResolutionChangeEvent() -> handle<copy>
         // GetDefaultDisplayResolutionChangeEvent() -> handle<copy>
         public ResultCode GetDefaultDisplayResolutionChangeEvent(ServiceCtx context)
         public ResultCode GetDefaultDisplayResolutionChangeEvent(ServiceCtx context)
         {
         {
-            if (context.Process.HandleTable.GenerateHandle(context.Device.System.DisplayResolutionChangeEvent.ReadableEvent, out int handle) != KernelResult.Success)
+            if (_displayResolutionChangedEventHandle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(context.Device.System.DisplayResolutionChangeEvent.ReadableEvent, out _displayResolutionChangedEventHandle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_displayResolutionChangedEventHandle);
 
 
             Logger.Stub?.PrintStub(LogClass.ServiceAm);
             Logger.Stub?.PrintStub(LogClass.ServiceAm);
 
 
@@ -189,7 +197,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
 
 
             _apmSystemManagerServer.SetCpuBoostMode((Apm.CpuBoostMode)cpuBoostMode);
             _apmSystemManagerServer.SetCpuBoostMode((Apm.CpuBoostMode)cpuBoostMode);
 
 
-            // TODO: It signals an internal event of ICommonStateGetter. We have to determine where this event is used. 
+            // TODO: It signals an internal event of ICommonStateGetter. We have to determine where this event is used.
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }

+ 7 - 3
Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs

@@ -9,6 +9,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
     class IHomeMenuFunctions : IpcService
     class IHomeMenuFunctions : IpcService
     {
     {
         private KEvent _channelEvent;
         private KEvent _channelEvent;
+        private int    _channelEventHandle;
 
 
         public IHomeMenuFunctions(Horizon system)
         public IHomeMenuFunctions(Horizon system)
         {
         {
@@ -29,12 +30,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
         // GetPopFromGeneralChannelEvent() -> handle<copy>
         // GetPopFromGeneralChannelEvent() -> handle<copy>
         public ResultCode GetPopFromGeneralChannelEvent(ServiceCtx context)
         public ResultCode GetPopFromGeneralChannelEvent(ServiceCtx context)
         {
         {
-            if (context.Process.HandleTable.GenerateHandle(_channelEvent.ReadableEvent, out int handle) != KernelResult.Success)
+            if (_channelEventHandle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(_channelEvent.ReadableEvent, out _channelEventHandle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_channelEventHandle);
 
 
             Logger.Stub?.PrintStub(LogClass.ServiceAm);
             Logger.Stub?.PrintStub(LogClass.ServiceAm);
 
 

+ 3 - 1
Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs

@@ -49,7 +49,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
             }
             }
 
 
             var data = new byte[transferMem.Size];
             var data = new byte[transferMem.Size];
-            context.Memory.Read(transferMem.Address, data);
+            transferMem.Creator.CpuMemory.Read(transferMem.Address, data);
+
+            context.Device.System.KernelContext.Syscall.CloseHandle(handle);
 
 
             MakeObject(context, new IStorage(data));
             MakeObject(context, new IStorage(data));
 
 

+ 37 - 5
Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs

@@ -8,10 +8,13 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
 {
 {
     class ISelfController : IpcService
     class ISelfController : IpcService
     {
     {
+        private readonly long _pid;
+
         private KEvent _libraryAppletLaunchableEvent;
         private KEvent _libraryAppletLaunchableEvent;
+        private int    _libraryAppletLaunchableEventHandle;
 
 
         private KEvent _accumulatedSuspendedTickChangedEvent;
         private KEvent _accumulatedSuspendedTickChangedEvent;
-        private int    _accumulatedSuspendedTickChangedEventHandle = 0;
+        private int    _accumulatedSuspendedTickChangedEventHandle;
 
 
         private object _fatalSectionLock = new object();
         private object _fatalSectionLock = new object();
         private int    _fatalSectionCount;
         private int    _fatalSectionCount;
@@ -32,9 +35,10 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
         private uint _screenShotImageOrientation = 0;
         private uint _screenShotImageOrientation = 0;
         private uint _idleTimeDetectionExtension = 0;
         private uint _idleTimeDetectionExtension = 0;
 
 
-        public ISelfController(Horizon system)
+        public ISelfController(Horizon system, long pid)
         {
         {
             _libraryAppletLaunchableEvent = new KEvent(system.KernelContext);
             _libraryAppletLaunchableEvent = new KEvent(system.KernelContext);
+            _pid = pid;
         }
         }
 
 
         [Command(0)]
         [Command(0)]
@@ -103,12 +107,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
         {
         {
             _libraryAppletLaunchableEvent.ReadableEvent.Signal();
             _libraryAppletLaunchableEvent.ReadableEvent.Signal();
 
 
-            if (context.Process.HandleTable.GenerateHandle(_libraryAppletLaunchableEvent.ReadableEvent, out int handle) != KernelResult.Success)
+            if (_libraryAppletLaunchableEventHandle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(_libraryAppletLaunchableEvent.ReadableEvent, out _libraryAppletLaunchableEventHandle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_libraryAppletLaunchableEventHandle);
 
 
             Logger.Stub?.PrintStub(LogClass.ServiceAm);
             Logger.Stub?.PrintStub(LogClass.ServiceAm);
 
 
@@ -206,6 +213,31 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }
 
 
+        [Command(40)]
+        // CreateManagedDisplayLayer() -> u64
+        public ResultCode CreateManagedDisplayLayer(ServiceCtx context)
+        {
+            context.Device.System.SurfaceFlinger.CreateLayer(_pid, out long layerId);
+
+            context.ResponseData.Write(layerId);
+
+            return ResultCode.Success;
+        }
+
+        [Command(44)] // 10.0.0+
+        // CreateManagedDisplaySeparableLayer() -> (u64, u64)
+        public ResultCode CreateManagedDisplaySeparableLayer(ServiceCtx context)
+        {
+            // NOTE: first create the recoding layer and then the display one because right now Surface Flinger only use the last id.
+            context.Device.System.SurfaceFlinger.CreateLayer(_pid, out long recordingLayerId);
+            context.Device.System.SurfaceFlinger.CreateLayer(_pid, out long displayLayerId);
+
+            context.ResponseData.Write(displayLayerId);
+            context.ResponseData.Write(recordingLayerId);
+
+            return ResultCode.Success;
+        }
+
         [Command(50)]
         [Command(50)]
         // SetHandlesRequestToDisplay(b8)
         // SetHandlesRequestToDisplay(b8)
         public ResultCode SetHandlesRequestToDisplay(ServiceCtx context)
         public ResultCode SetHandlesRequestToDisplay(ServiceCtx context)

+ 9 - 2
Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IWindowController.cs

@@ -4,7 +4,12 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
 {
 {
     class IWindowController : IpcService
     class IWindowController : IpcService
     {
     {
-        public IWindowController() { }
+        private readonly long _pid;
+
+        public IWindowController(long pid)
+        {
+            _pid = pid;
+        }
 
 
         [Command(1)]
         [Command(1)]
         // GetAppletResourceUserId() -> nn::applet::AppletResourceUserId
         // GetAppletResourceUserId() -> nn::applet::AppletResourceUserId
@@ -12,7 +17,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
         {
         {
             Logger.Stub?.PrintStub(LogClass.ServiceAm);
             Logger.Stub?.PrintStub(LogClass.ServiceAm);
 
 
-            context.ResponseData.Write(0L);
+            long appletResourceUserId = context.Device.System.AppletState.AppletResourceUserIds.Add(_pid);
+
+            context.ResponseData.Write(appletResourceUserId);
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }

+ 1 - 1
Ryujinx.HLE/HOS/Services/Am/AppletAE/IAllSystemAppletProxiesService.cs

@@ -11,7 +11,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
         // OpenSystemAppletProxy(u64, pid, handle<copy>) -> object<nn::am::service::ISystemAppletProxy>
         // OpenSystemAppletProxy(u64, pid, handle<copy>) -> object<nn::am::service::ISystemAppletProxy>
         public ResultCode OpenSystemAppletProxy(ServiceCtx context)
         public ResultCode OpenSystemAppletProxy(ServiceCtx context)
         {
         {
-            MakeObject(context, new ISystemAppletProxy());
+            MakeObject(context, new ISystemAppletProxy(context.Request.HandleDesc.PId));
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }

+ 27 - 16
Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs

@@ -28,6 +28,10 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
         private KEvent _friendInvitationStorageChannelEvent;
         private KEvent _friendInvitationStorageChannelEvent;
         private KEvent _notificationStorageChannelEvent;
         private KEvent _notificationStorageChannelEvent;
 
 
+        private int _gpuErrorDetectedSystemEventHandle;
+        private int _friendInvitationStorageChannelEventHandle;
+        private int _notificationStorageChannelEventHandle;
+
         public IApplicationFunctions(Horizon system)
         public IApplicationFunctions(Horizon system)
         {
         {
             _gpuErrorDetectedSystemEvent         = new KEvent(system.KernelContext);
             _gpuErrorDetectedSystemEvent         = new KEvent(system.KernelContext);
@@ -122,7 +126,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
                 return ResultCode.Success;
                 return ResultCode.Success;
             }
             }
 
 
-            // If desired language is not supported by application, use first supported language from TitleLanguage. 
+            // If desired language is not supported by application, use first supported language from TitleLanguage.
             // TODO: In the future, a GUI could enable user-specified search priority
             // TODO: In the future, a GUI could enable user-specified search priority
             if (((1 << (int)context.Device.System.State.DesiredTitleLanguage) & supportedLanguages) == 0)
             if (((1 << (int)context.Device.System.State.DesiredTitleLanguage) & supportedLanguages) == 0)
             {
             {
@@ -293,12 +297,10 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
                 resultCode = InitializeApplicationCopyrightFrameBufferImpl(transferMemoryAddress, transferMemorySize, width, height);
                 resultCode = InitializeApplicationCopyrightFrameBufferImpl(transferMemoryAddress, transferMemorySize, width, height);
             }
             }
 
 
-            /*
-            if (transferMemoryHandle)
+            if (transferMemoryHandle != 0)
             {
             {
-                svcCloseHandle(transferMemoryHandle);
+                context.Device.System.KernelContext.Syscall.CloseHandle(transferMemoryHandle);
             }
             }
-            */
 
 
             return resultCode;
             return resultCode;
         }
         }
@@ -455,15 +457,18 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
         // GetGpuErrorDetectedSystemEvent() -> handle<copy>
         // GetGpuErrorDetectedSystemEvent() -> handle<copy>
         public ResultCode GetGpuErrorDetectedSystemEvent(ServiceCtx context)
         public ResultCode GetGpuErrorDetectedSystemEvent(ServiceCtx context)
         {
         {
-            if (context.Process.HandleTable.GenerateHandle(_gpuErrorDetectedSystemEvent.ReadableEvent, out int gpuErrorDetectedSystemEventHandle) != KernelResult.Success)
+            if (_gpuErrorDetectedSystemEventHandle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(_gpuErrorDetectedSystemEvent.ReadableEvent, out _gpuErrorDetectedSystemEventHandle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(gpuErrorDetectedSystemEventHandle);
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_gpuErrorDetectedSystemEventHandle);
 
 
-            // NOTE: This is used by "sdk" NSO during applet-application initialization. 
-            //       A seperate thread is setup where event-waiting is handled. 
+            // NOTE: This is used by "sdk" NSO during applet-application initialization.
+            //       A seperate thread is setup where event-waiting is handled.
             //       When the Event is signaled, official sw will assert.
             //       When the Event is signaled, official sw will assert.
 
 
             return ResultCode.Success;
             return ResultCode.Success;
@@ -473,12 +478,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
         // GetFriendInvitationStorageChannelEvent() -> handle<copy>
         // GetFriendInvitationStorageChannelEvent() -> handle<copy>
         public ResultCode GetFriendInvitationStorageChannelEvent(ServiceCtx context)
         public ResultCode GetFriendInvitationStorageChannelEvent(ServiceCtx context)
         {
         {
-            if (context.Process.HandleTable.GenerateHandle(_friendInvitationStorageChannelEvent.ReadableEvent, out int friendInvitationStorageChannelEventHandle) != KernelResult.Success)
+            if (_friendInvitationStorageChannelEventHandle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(_friendInvitationStorageChannelEvent.ReadableEvent, out _friendInvitationStorageChannelEventHandle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(friendInvitationStorageChannelEventHandle);
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_friendInvitationStorageChannelEventHandle);
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }
@@ -501,12 +509,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati
         // GetNotificationStorageChannelEvent() -> handle<copy>
         // GetNotificationStorageChannelEvent() -> handle<copy>
         public ResultCode GetNotificationStorageChannelEvent(ServiceCtx context)
         public ResultCode GetNotificationStorageChannelEvent(ServiceCtx context)
         {
         {
-            if (context.Process.HandleTable.GenerateHandle(_notificationStorageChannelEvent.ReadableEvent, out int notificationStorageChannelEventHandle) != KernelResult.Success)
+            if (_notificationStorageChannelEventHandle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(_notificationStorageChannelEvent.ReadableEvent, out _notificationStorageChannelEventHandle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(notificationStorageChannelEventHandle);
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_notificationStorageChannelEventHandle);
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }

+ 8 - 3
Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs

@@ -5,7 +5,12 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService
 {
 {
     class IApplicationProxy : IpcService
     class IApplicationProxy : IpcService
     {
     {
-        public IApplicationProxy() { }
+        private readonly long _pid;
+
+        public IApplicationProxy(long pid)
+        {
+            _pid = pid;
+        }
 
 
         [Command(0)]
         [Command(0)]
         // GetCommonStateGetter() -> object<nn::am::service::ICommonStateGetter>
         // GetCommonStateGetter() -> object<nn::am::service::ICommonStateGetter>
@@ -20,7 +25,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService
         // GetSelfController() -> object<nn::am::service::ISelfController>
         // GetSelfController() -> object<nn::am::service::ISelfController>
         public ResultCode GetSelfController(ServiceCtx context)
         public ResultCode GetSelfController(ServiceCtx context)
         {
         {
-            MakeObject(context, new ISelfController(context.Device.System));
+            MakeObject(context, new ISelfController(context.Device.System, _pid));
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }
@@ -29,7 +34,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService
         // GetWindowController() -> object<nn::am::service::IWindowController>
         // GetWindowController() -> object<nn::am::service::IWindowController>
         public ResultCode GetWindowController(ServiceCtx context)
         public ResultCode GetWindowController(ServiceCtx context)
         {
         {
-            MakeObject(context, new IWindowController());
+            MakeObject(context, new IWindowController(_pid));
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }

+ 1 - 1
Ryujinx.HLE/HOS/Services/Am/AppletOE/IApplicationProxyService.cs

@@ -11,7 +11,7 @@ namespace Ryujinx.HLE.HOS.Services.Am
         // OpenApplicationProxy(u64, pid, handle<copy>) -> object<nn::am::service::IApplicationProxy>
         // OpenApplicationProxy(u64, pid, handle<copy>) -> object<nn::am::service::IApplicationProxy>
         public ResultCode OpenApplicationProxy(ServiceCtx context)
         public ResultCode OpenApplicationProxy(ServiceCtx context)
         {
         {
-            MakeObject(context, new IApplicationProxy());
+            MakeObject(context, new IApplicationProxy(context.Request.HandleDesc.PId));
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }

+ 14 - 8
Ryujinx.HLE/HOS/Services/Audio/AudioOutManager/IAudioOut.cs

@@ -10,15 +10,18 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioOutManager
 {
 {
     class IAudioOut : IpcService, IDisposable
     class IAudioOut : IpcService, IDisposable
     {
     {
-        private IAalOutput _audioOut;
-        private KEvent     _releaseEvent;
-        private int        _track;
+        private readonly IAalOutput _audioOut;
+        private readonly KEvent     _releaseEvent;
+        private          int        _releaseEventHandle;
+        private readonly int        _track;
+        private readonly int        _clientHandle;
 
 
-        public IAudioOut(IAalOutput audioOut, KEvent releaseEvent, int track)
+        public IAudioOut(IAalOutput audioOut, KEvent releaseEvent, int track, int clientHandle)
         {
         {
             _audioOut     = audioOut;
             _audioOut     = audioOut;
             _releaseEvent = releaseEvent;
             _releaseEvent = releaseEvent;
             _track        = track;
             _track        = track;
+            _clientHandle = clientHandle;
         }
         }
 
 
         [Command(0)]
         [Command(0)]
@@ -59,12 +62,15 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioOutManager
         // RegisterBufferEvent() -> handle<copy>
         // RegisterBufferEvent() -> handle<copy>
         public ResultCode RegisterBufferEvent(ServiceCtx context)
         public ResultCode RegisterBufferEvent(ServiceCtx context)
         {
         {
-            if (context.Process.HandleTable.GenerateHandle(_releaseEvent.ReadableEvent, out int handle) != KernelResult.Success)
+            if (_releaseEventHandle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(_releaseEvent.ReadableEvent, out _releaseEventHandle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_releaseEventHandle);
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }
@@ -108,7 +114,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioOutManager
             // NOTE: Assume PCM16 all the time, change if new format are found.
             // NOTE: Assume PCM16 all the time, change if new format are found.
             short[] buffer = new short[data.SampleBufferSize / sizeof(short)];
             short[] buffer = new short[data.SampleBufferSize / sizeof(short)];
 
 
-            context.Memory.Read((ulong)data.SampleBufferPtr, MemoryMarshal.Cast<short, byte>(buffer));
+            context.Process.HandleTable.GetKProcess(_clientHandle).CpuMemory.Read((ulong)data.SampleBufferPtr, MemoryMarshal.Cast<short, byte>(buffer));
 
 
             _audioOut.AppendBuffer(_track, tag, buffer);
             _audioOut.AppendBuffer(_track, tag, buffer);
 
 

+ 3 - 1
Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager.cs

@@ -33,7 +33,9 @@ namespace Ryujinx.HLE.HOS.Services.Audio
 
 
         public ResultCode OpenAudioRenderer(ServiceCtx context, out IAudioRenderer obj, ref AudioRendererConfiguration parameter, ulong workBufferSize, ulong appletResourceUserId, KTransferMemory workBufferTransferMemory, uint processHandle)
         public ResultCode OpenAudioRenderer(ServiceCtx context, out IAudioRenderer obj, ref AudioRendererConfiguration parameter, ulong workBufferSize, ulong appletResourceUserId, KTransferMemory workBufferTransferMemory, uint processHandle)
         {
         {
-            ResultCode result = (ResultCode)_impl.OpenAudioRenderer(out AudioRenderSystem renderer, context.Memory, ref parameter, appletResourceUserId, workBufferTransferMemory.Address, workBufferTransferMemory.Size, processHandle);
+            var memoryManager = context.Process.HandleTable.GetKProcess((int)processHandle).CpuMemory;
+
+            ResultCode result = (ResultCode)_impl.OpenAudioRenderer(out AudioRenderSystem renderer, memoryManager, ref parameter, appletResourceUserId, workBufferTransferMemory.Address, workBufferTransferMemory.Size, processHandle);
 
 
             if (result == ResultCode.Success)
             if (result == ResultCode.Success)
             {
             {

+ 4 - 2
Ryujinx.HLE/HOS/Services/Audio/AudioRendererManagerServer.cs

@@ -14,9 +14,9 @@ namespace Ryujinx.HLE.HOS.Services.Audio
 
 
         private IAudioRendererManager _impl;
         private IAudioRendererManager _impl;
 
 
-        public AudioRendererManagerServer(ServiceCtx context) : this(new AudioRendererManager(context.Device.System.AudioRendererManager, context.Device.System.AudioDeviceSessionRegistry)) { }
+        public AudioRendererManagerServer(ServiceCtx context) : this(context, new AudioRendererManager(context.Device.System.AudioRendererManager, context.Device.System.AudioDeviceSessionRegistry)) { }
 
 
-        public AudioRendererManagerServer(IAudioRendererManager impl) : base(new ServerBase("AudioRendererServer"))
+        public AudioRendererManagerServer(ServiceCtx context, IAudioRendererManager impl) : base(new ServerBase(context.Device.System.KernelContext, "AudioRendererServer"))
         {
         {
             _impl = impl;
             _impl = impl;
         }
         }
@@ -40,6 +40,8 @@ namespace Ryujinx.HLE.HOS.Services.Audio
                 MakeObject(context, new AudioRendererServer(renderer));
                 MakeObject(context, new AudioRendererServer(renderer));
             }
             }
 
 
+            context.Device.System.KernelContext.Syscall.CloseHandle((int)processHandle);
+
             return result;
             return result;
         }
         }
 
 

+ 2 - 1
Ryujinx.HLE/HOS/Services/Audio/IAudioInManager.cs

@@ -1,4 +1,5 @@
 using Ryujinx.Cpu;
 using Ryujinx.Cpu;
+using Ryujinx.Memory;
 using System;
 using System;
 using System.Text;
 using System.Text;
 
 
@@ -57,7 +58,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }
 
 
-        private uint ListAudioInsImpl(MemoryManager memory, long bufferPosition, long bufferSize, bool filtered = false)
+        private uint ListAudioInsImpl(IVirtualMemoryManager memory, long bufferPosition, long bufferSize, bool filtered = false)
         {
         {
             uint count = 0;
             uint count = 0;
 
 

+ 2 - 2
Ryujinx.HLE/HOS/Services/Audio/IAudioOutManager.cs

@@ -14,7 +14,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio
         private const int    DefaultSampleRate    = 48000;
         private const int    DefaultSampleRate    = 48000;
         private const int    DefaultChannelsCount = 2;
         private const int    DefaultChannelsCount = 2;
 
 
-        public IAudioOutManager(ServiceCtx context) : base(new ServerBase("AudioOutServer")) { }
+        public IAudioOutManager(ServiceCtx context) : base(new ServerBase(context.Device.System.KernelContext, "AudioOutServer")) { }
 
 
         [Command(0)]
         [Command(0)]
         // ListAudioOuts() -> (u32 count, buffer<bytes, 6>)
         // ListAudioOuts() -> (u32 count, buffer<bytes, 6>)
@@ -134,7 +134,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio
 
 
             int track = audioOut.OpenTrack(sampleRate, channels, callback);
             int track = audioOut.OpenTrack(sampleRate, channels, callback);
 
 
-            MakeObject(context, new IAudioOut(audioOut, releaseEvent, track));
+            MakeObject(context, new IAudioOut(audioOut, releaseEvent, track, context.Request.HandleDesc.ToCopy[0]));
 
 
             context.ResponseData.Write(sampleRate);
             context.ResponseData.Write(sampleRate);
             context.ResponseData.Write(channels);
             context.ResponseData.Write(channels);

+ 3 - 0
Ryujinx.HLE/HOS/Services/Audio/IHardwareOpusDecoderManager.cs

@@ -16,6 +16,9 @@ namespace Ryujinx.HLE.HOS.Services.Audio
 
 
             MakeObject(context, new IHardwareOpusDecoder(sampleRate, channelsCount));
             MakeObject(context, new IHardwareOpusDecoder(sampleRate, channelsCount));
 
 
+            // Close transfer memory immediately as we don't use it.
+            context.Device.System.KernelContext.Syscall.CloseHandle(context.Request.HandleDesc.ToCopy[0]);
+
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }
 
 

+ 7 - 3
Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs

@@ -12,6 +12,7 @@ namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
     class IDeliveryCacheProgressService : IpcService
     class IDeliveryCacheProgressService : IpcService
     {
     {
         private KEvent _event;
         private KEvent _event;
+        private int    _eventHandle;
 
 
         public IDeliveryCacheProgressService(ServiceCtx context)
         public IDeliveryCacheProgressService(ServiceCtx context)
         {
         {
@@ -22,12 +23,15 @@ namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
         // GetEvent() -> handle<copy>
         // GetEvent() -> handle<copy>
         public ResultCode GetEvent(ServiceCtx context)
         public ResultCode GetEvent(ServiceCtx context)
         {
         {
-            if (context.Process.HandleTable.GenerateHandle(_event.ReadableEvent, out int handle) != KernelResult.Success)
+            if (_eventHandle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(_event.ReadableEvent, out _eventHandle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_eventHandle);
 
 
             Logger.Stub?.PrintStub(LogClass.ServiceBcat);
             Logger.Stub?.PrintStub(LogClass.ServiceBcat);
 
 

+ 6 - 16
Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs

@@ -33,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
         }
         }
 
 
         [Command(8)]
         [Command(8)]
-        // OpenFileSystemWithId(nn::fssrv::sf::FileSystemType filesystem_type, nn::ApplicationId tid, buffer<bytes<0x301>, 0x19, 0x301> path) 
+        // OpenFileSystemWithId(nn::fssrv::sf::FileSystemType filesystem_type, nn::ApplicationId tid, buffer<bytes<0x301>, 0x19, 0x301> path)
         // -> object<nn::fssrv::sf::IFileSystem> contentFs
         // -> object<nn::fssrv::sf::IFileSystem> contentFs
         public ResultCode OpenFileSystemWithId(ServiceCtx context)
         public ResultCode OpenFileSystemWithId(ServiceCtx context)
         {
         {
@@ -138,12 +138,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
             // Workaround that by setting the application ID and owner ID if they're not already set
             // Workaround that by setting the application ID and owner ID if they're not already set
             if (attribute.ProgramId == ProgramId.InvalidId)
             if (attribute.ProgramId == ProgramId.InvalidId)
             {
             {
-                attribute.ProgramId = new ProgramId(context.Process.TitleId);
-            }
-
-            if (creationInfo.OwnerId == 0)
-            {
-                creationInfo.OwnerId = 0;
+                attribute.ProgramId = new ProgramId(context.Device.Application.TitleId);
             }
             }
 
 
             Logger.Info?.Print(LogClass.ServiceFs, $"Creating save with title ID {attribute.ProgramId.Value:x16}");
             Logger.Info?.Print(LogClass.ServiceFs, $"Creating save with title ID {attribute.ProgramId.Value:x16}");
@@ -215,12 +210,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
             // Workaround that by setting the application ID and owner ID if they're not already set
             // Workaround that by setting the application ID and owner ID if they're not already set
             if (attribute.ProgramId == ProgramId.InvalidId)
             if (attribute.ProgramId == ProgramId.InvalidId)
             {
             {
-                attribute.ProgramId = new ProgramId(context.Process.TitleId);
-            }
-
-            if (creationInfo.OwnerId == 0)
-            {
-                creationInfo.OwnerId = 0;
+                attribute.ProgramId = new ProgramId(context.Device.Application.TitleId);
             }
             }
 
 
             Result result = _baseFileSystemProxy.CreateSaveDataFileSystemWithHashSalt(ref attribute, ref creationInfo, ref metaCreateInfo, ref hashSalt);
             Result result = _baseFileSystemProxy.CreateSaveDataFileSystemWithHashSalt(ref attribute, ref creationInfo, ref metaCreateInfo, ref hashSalt);
@@ -239,7 +229,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
             // Workaround that by setting the application ID if it's not already set
             // Workaround that by setting the application ID if it's not already set
             if (attribute.ProgramId == ProgramId.InvalidId)
             if (attribute.ProgramId == ProgramId.InvalidId)
             {
             {
-                attribute.ProgramId = new ProgramId(context.Process.TitleId);
+                attribute.ProgramId = new ProgramId(context.Device.Application.TitleId);
             }
             }
 
 
             Result result = _baseFileSystemProxy.OpenSaveDataFileSystem(out LibHac.Fs.Fsa.IFileSystem fileSystem, spaceId, ref attribute);
             Result result = _baseFileSystemProxy.OpenSaveDataFileSystem(out LibHac.Fs.Fsa.IFileSystem fileSystem, spaceId, ref attribute);
@@ -280,7 +270,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
             // Workaround that by setting the application ID if it's not already set
             // Workaround that by setting the application ID if it's not already set
             if (attribute.ProgramId == ProgramId.InvalidId)
             if (attribute.ProgramId == ProgramId.InvalidId)
             {
             {
-                attribute.ProgramId = new ProgramId(context.Process.TitleId);
+                attribute.ProgramId = new ProgramId(context.Device.Application.TitleId);
             }
             }
 
 
             Result result = _baseFileSystemProxy.OpenReadOnlySaveDataFileSystem(out LibHac.Fs.Fsa.IFileSystem fileSystem, spaceId, ref attribute);
             Result result = _baseFileSystemProxy.OpenReadOnlySaveDataFileSystem(out LibHac.Fs.Fsa.IFileSystem fileSystem, spaceId, ref attribute);
@@ -328,7 +318,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
             filter.SetSaveDataType(SaveDataType.Cache);
             filter.SetSaveDataType(SaveDataType.Cache);
             filter.SetProgramId(new ProgramId(context.Process.TitleId));
             filter.SetProgramId(new ProgramId(context.Process.TitleId));
 
 
-            // FS would query the User and SdCache space IDs to find where the existing cache is (if any). 
+            // FS would query the User and SdCache space IDs to find where the existing cache is (if any).
             // We always have the SD card inserted, so we can always use SdCache for now.
             // We always have the SD card inserted, so we can always use SdCache for now.
             Result result = _baseFileSystemProxy.OpenSaveDataInfoReaderBySaveDataSpaceId(
             Result result = _baseFileSystemProxy.OpenSaveDataInfoReaderBySaveDataSpaceId(
                 out ReferenceCountedDisposable<LibHac.FsSrv.ISaveDataInfoReader> infoReader, SaveDataSpaceId.SdCache);
                 out ReferenceCountedDisposable<LibHac.FsSrv.ISaveDataInfoReader> infoReader, SaveDataSpaceId.SdCache);

+ 7 - 3
Ryujinx.HLE/HOS/Services/Hid/HidServer/IAppletResource.cs

@@ -8,6 +8,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.HidServer
     class IAppletResource : IpcService
     class IAppletResource : IpcService
     {
     {
         private KSharedMemory _hidSharedMem;
         private KSharedMemory _hidSharedMem;
+        private int           _hidSharedMemHandle;
 
 
         public IAppletResource(KSharedMemory hidSharedMem)
         public IAppletResource(KSharedMemory hidSharedMem)
         {
         {
@@ -18,12 +19,15 @@ namespace Ryujinx.HLE.HOS.Services.Hid.HidServer
         // GetSharedMemoryHandle() -> handle<copy>
         // GetSharedMemoryHandle() -> handle<copy>
         public ResultCode GetSharedMemoryHandle(ServiceCtx context)
         public ResultCode GetSharedMemoryHandle(ServiceCtx context)
         {
         {
-            if (context.Process.HandleTable.GenerateHandle(_hidSharedMem, out int handle) != KernelResult.Success)
+            if (_hidSharedMemHandle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(_hidSharedMem, out _hidSharedMemHandle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_hidSharedMemHandle);
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }

+ 12 - 12
Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs

@@ -35,7 +35,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
         private HidAccelerometerParameters _accelerometerParams;
         private HidAccelerometerParameters _accelerometerParams;
         private HidVibrationValue          _vibrationValue;
         private HidVibrationValue          _vibrationValue;
 
 
-        public IHidServer(ServiceCtx context) : base(new ServerBase("HidServer"))
+        public IHidServer(ServiceCtx context) : base(new ServerBase(context.Device.System.KernelContext, "HidServer"))
         {
         {
             _xpadIdEvent                 = new KEvent(context.Device.System.KernelContext);
             _xpadIdEvent                 = new KEvent(context.Device.System.KernelContext);
             _palmaOperationCompleteEvent = new KEvent(context.Device.System.KernelContext);
             _palmaOperationCompleteEvent = new KEvent(context.Device.System.KernelContext);
@@ -559,9 +559,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid
             ControllerType type = (ControllerType)context.RequestData.ReadInt32();
             ControllerType type = (ControllerType)context.RequestData.ReadInt32();
             long appletResourceUserId = context.RequestData.ReadInt64();
             long appletResourceUserId = context.RequestData.ReadInt64();
 
 
-            Logger.Stub?.PrintStub(LogClass.ServiceHid, new { 
-                    appletResourceUserId, 
-                    type 
+            Logger.Stub?.PrintStub(LogClass.ServiceHid, new {
+                    appletResourceUserId,
+                    type
                 });
                 });
 
 
             context.Device.Hid.Npads.SupportedStyleSets = type;
             context.Device.Hid.Npads.SupportedStyleSets = type;
@@ -577,9 +577,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid
 
 
             context.ResponseData.Write((int)context.Device.Hid.Npads.SupportedStyleSets);
             context.ResponseData.Write((int)context.Device.Hid.Npads.SupportedStyleSets);
 
 
-            Logger.Stub?.PrintStub(LogClass.ServiceHid, new { 
+            Logger.Stub?.PrintStub(LogClass.ServiceHid, new {
                     appletResourceUserId,
                     appletResourceUserId,
-                    context.Device.Hid.Npads.SupportedStyleSets 
+                    context.Device.Hid.Npads.SupportedStyleSets
                 });
                 });
 
 
             return ResultCode.Success;
             return ResultCode.Success;
@@ -704,9 +704,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid
             long appletResourceUserId = context.RequestData.ReadInt64();
             long appletResourceUserId = context.RequestData.ReadInt64();
             context.Device.Hid.Npads.JoyHold = (NpadJoyHoldType)context.RequestData.ReadInt64();
             context.Device.Hid.Npads.JoyHold = (NpadJoyHoldType)context.RequestData.ReadInt64();
 
 
-            Logger.Stub?.PrintStub(LogClass.ServiceHid, new { 
-                    appletResourceUserId, 
-                    context.Device.Hid.Npads.JoyHold 
+            Logger.Stub?.PrintStub(LogClass.ServiceHid, new {
+                    appletResourceUserId,
+                    context.Device.Hid.Npads.JoyHold
                 });
                 });
 
 
             return ResultCode.Success;
             return ResultCode.Success;
@@ -720,9 +720,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid
 
 
             context.ResponseData.Write((long)context.Device.Hid.Npads.JoyHold);
             context.ResponseData.Write((long)context.Device.Hid.Npads.JoyHold);
 
 
-            Logger.Stub?.PrintStub(LogClass.ServiceHid, new { 
-                    appletResourceUserId, 
-                    context.Device.Hid.Npads.JoyHold 
+            Logger.Stub?.PrintStub(LogClass.ServiceHid, new {
+                    appletResourceUserId,
+                    context.Device.Hid.Npads.JoyHold
                 });
                 });
 
 
             return ResultCode.Success;
             return ResultCode.Success;

+ 24 - 38
Ryujinx.HLE/HOS/Services/IpcService.cs

@@ -1,8 +1,6 @@
 using Ryujinx.Common.Logging;
 using Ryujinx.Common.Logging;
 using Ryujinx.HLE.Exceptions;
 using Ryujinx.HLE.Exceptions;
 using Ryujinx.HLE.HOS.Ipc;
 using Ryujinx.HLE.HOS.Ipc;
-using Ryujinx.HLE.HOS.Kernel.Common;
-using Ryujinx.HLE.HOS.Kernel.Ipc;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.IO;
 using System.IO;
@@ -17,6 +15,7 @@ namespace Ryujinx.HLE.HOS.Services
 
 
         public ServerBase Server { get; private set; }
         public ServerBase Server { get; private set; }
 
 
+        private IpcService _parent;
         private IdDictionary _domainObjects;
         private IdDictionary _domainObjects;
         private int _selfId;
         private int _selfId;
         private bool _isDomain;
         private bool _isDomain;
@@ -32,6 +31,7 @@ namespace Ryujinx.HLE.HOS.Services
 
 
             Server = server;
             Server = server;
 
 
+            _parent = this;
             _domainObjects = new IdDictionary();
             _domainObjects = new IdDictionary();
             _selfId = -1;
             _selfId = -1;
         }
         }
@@ -62,8 +62,8 @@ namespace Ryujinx.HLE.HOS.Services
                 int domainWord0 = context.RequestData.ReadInt32();
                 int domainWord0 = context.RequestData.ReadInt32();
                 int domainObjId = context.RequestData.ReadInt32();
                 int domainObjId = context.RequestData.ReadInt32();
 
 
-                int domainCmd       = (domainWord0 >> 0)  & 0xff;
-                int inputObjCount   = (domainWord0 >> 8)  & 0xff;
+                int domainCmd = (domainWord0 >> 0) & 0xff;
+                int inputObjCount = (domainWord0 >> 8) & 0xff;
                 int dataPayloadSize = (domainWord0 >> 16) & 0xffff;
                 int dataPayloadSize = (domainWord0 >> 16) & 0xffff;
 
 
                 context.RequestData.BaseStream.Seek(0x10 + dataPayloadSize, SeekOrigin.Begin);
                 context.RequestData.BaseStream.Seek(0x10 + dataPayloadSize, SeekOrigin.Begin);
@@ -96,8 +96,8 @@ namespace Ryujinx.HLE.HOS.Services
                 }
                 }
             }
             }
 
 
-            long sfciMagic =      context.RequestData.ReadInt64();
-            int  commandId = (int)context.RequestData.ReadInt64();
+            long sfciMagic = context.RequestData.ReadInt64();
+            int commandId = (int)context.RequestData.ReadInt64();
 
 
             bool serviceExists = service.Commands.TryGetValue(commandId, out MethodInfo processRequest);
             bool serviceExists = service.Commands.TryGetValue(commandId, out MethodInfo processRequest);
 
 
@@ -145,56 +145,37 @@ namespace Ryujinx.HLE.HOS.Services
             {
             {
                 string dbgMessage = $"{service.GetType().FullName}: {commandId}";
                 string dbgMessage = $"{service.GetType().FullName}: {commandId}";
 
 
-                throw new ServiceNotImplementedException(context, dbgMessage);
+                throw new ServiceNotImplementedException(service, context, dbgMessage);
             }
             }
         }
         }
 
 
-        protected static void MakeObject(ServiceCtx context, IpcService obj)
+        protected void MakeObject(ServiceCtx context, IpcService obj)
         {
         {
-            IpcService service = context.Session.Service;
+            obj.TrySetServer(_parent.Server);
 
 
-            obj.TrySetServer(service.Server);
-
-            if (service._isDomain)
+            if (_parent._isDomain)
             {
             {
-                context.Response.ObjectIds.Add(service.Add(obj));
+                obj._parent = _parent;
+
+                context.Response.ObjectIds.Add(_parent.Add(obj));
             }
             }
             else
             else
             {
             {
-                KSession session = new KSession(context.Device.System.KernelContext);
-
-                session.ClientSession.Service = obj;
-
-                if (context.Process.HandleTable.GenerateHandle(session.ClientSession, out int handle) != KernelResult.Success)
-                {
-                    throw new InvalidOperationException("Out of handles!");
-                }
+                context.Device.System.KernelContext.Syscall.CreateSession(false, 0, out int serverSessionHandle, out int clientSessionHandle);
 
 
-                session.ServerSession.DecrementReferenceCount();
-                session.ClientSession.DecrementReferenceCount();
+                obj.Server.AddSessionObj(serverSessionHandle, obj);
 
 
-                context.Response.HandleDesc = IpcHandleDesc.MakeMove(handle);
+                context.Response.HandleDesc = IpcHandleDesc.MakeMove(clientSessionHandle);
             }
             }
         }
         }
 
 
-        protected static T GetObject<T>(ServiceCtx context, int index) where T : IpcService
+        protected T GetObject<T>(ServiceCtx context, int index) where T : IpcService
         {
         {
-            IpcService service = context.Session.Service;
-
-            if (!service._isDomain)
-            {
-                int handle = context.Request.HandleDesc.ToMove[index];
-
-                KClientSession session = context.Process.HandleTable.GetObject<KClientSession>(handle);
-
-                return session?.Service is T ? (T)session.Service : null;
-            }
-
             int objId = context.Request.ObjectIds[index];
             int objId = context.Request.ObjectIds[index];
 
 
-            IIpcService obj = service.GetObject(objId);
+            IIpcService obj = _parent.GetObject(objId);
 
 
-            return obj is T ? (T)obj : null;
+            return obj is T t ? t : null;
         }
         }
 
 
         public bool TrySetServer(ServerBase newServer)
         public bool TrySetServer(ServerBase newServer)
@@ -230,5 +211,10 @@ namespace Ryujinx.HLE.HOS.Services
         {
         {
             return _domainObjects.GetData<IIpcService>(id);
             return _domainObjects.GetData<IIpcService>(id);
         }
         }
+
+        public void SetParent(IpcService parent)
+        {
+            _parent = parent._parent;
+        }
     }
     }
 }
 }

+ 16 - 16
Ryujinx.HLE/HOS/Services/Nfc/Nfp/UserManager/IUser.cs

@@ -103,98 +103,98 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
         // StartDetection(bytes<8, 4>)
         // StartDetection(bytes<8, 4>)
         public ResultCode StartDetection(ServiceCtx context)
         public ResultCode StartDetection(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(4)]
         [Command(4)]
         // StopDetection(bytes<8, 4>)
         // StopDetection(bytes<8, 4>)
         public ResultCode StopDetection(ServiceCtx context)
         public ResultCode StopDetection(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(5)]
         [Command(5)]
         // Mount(bytes<8, 4>, u32, u32)
         // Mount(bytes<8, 4>, u32, u32)
         public ResultCode Mount(ServiceCtx context)
         public ResultCode Mount(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(6)]
         [Command(6)]
         // Unmount(bytes<8, 4>)
         // Unmount(bytes<8, 4>)
         public ResultCode Unmount(ServiceCtx context)
         public ResultCode Unmount(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(7)]
         [Command(7)]
         // OpenApplicationArea(bytes<8, 4>, u32)
         // OpenApplicationArea(bytes<8, 4>, u32)
         public ResultCode OpenApplicationArea(ServiceCtx context)
         public ResultCode OpenApplicationArea(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(8)]
         [Command(8)]
         // GetApplicationArea(bytes<8, 4>) -> (u32, buffer<unknown, 6>)
         // GetApplicationArea(bytes<8, 4>) -> (u32, buffer<unknown, 6>)
         public ResultCode GetApplicationArea(ServiceCtx context)
         public ResultCode GetApplicationArea(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(9)]
         [Command(9)]
         // SetApplicationArea(bytes<8, 4>, buffer<unknown, 5>)
         // SetApplicationArea(bytes<8, 4>, buffer<unknown, 5>)
         public ResultCode SetApplicationArea(ServiceCtx context)
         public ResultCode SetApplicationArea(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(10)]
         [Command(10)]
         // Flush(bytes<8, 4>)
         // Flush(bytes<8, 4>)
         public ResultCode Flush(ServiceCtx context)
         public ResultCode Flush(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(11)]
         [Command(11)]
         // Restore(bytes<8, 4>)
         // Restore(bytes<8, 4>)
         public ResultCode Restore(ServiceCtx context)
         public ResultCode Restore(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(12)]
         [Command(12)]
         // CreateApplicationArea(bytes<8, 4>, u32, buffer<unknown, 5>)
         // CreateApplicationArea(bytes<8, 4>, u32, buffer<unknown, 5>)
         public ResultCode CreateApplicationArea(ServiceCtx context)
         public ResultCode CreateApplicationArea(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(13)]
         [Command(13)]
         // GetTagInfo(bytes<8, 4>) -> buffer<unknown<0x58>, 0x1a>
         // GetTagInfo(bytes<8, 4>) -> buffer<unknown<0x58>, 0x1a>
         public ResultCode GetTagInfo(ServiceCtx context)
         public ResultCode GetTagInfo(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(14)]
         [Command(14)]
         // GetRegisterInfo(bytes<8, 4>) -> buffer<unknown<0x100>, 0x1a>
         // GetRegisterInfo(bytes<8, 4>) -> buffer<unknown<0x100>, 0x1a>
         public ResultCode GetRegisterInfo(ServiceCtx context)
         public ResultCode GetRegisterInfo(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(15)]
         [Command(15)]
         // GetCommonInfo(bytes<8, 4>) -> buffer<unknown<0x40>, 0x1a>
         // GetCommonInfo(bytes<8, 4>) -> buffer<unknown<0x40>, 0x1a>
         public ResultCode GetCommonInfo(ServiceCtx context)
         public ResultCode GetCommonInfo(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(16)]
         [Command(16)]
         // GetModelInfo(bytes<8, 4>) -> buffer<unknown<0x40>, 0x1a>
         // GetModelInfo(bytes<8, 4>) -> buffer<unknown<0x40>, 0x1a>
         public ResultCode GetModelInfo(ServiceCtx context)
         public ResultCode GetModelInfo(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(17)]
         [Command(17)]
@@ -308,7 +308,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
         // GetApplicationAreaSize(bytes<8, 4>) -> u32
         // GetApplicationAreaSize(bytes<8, 4>) -> u32
         public ResultCode GetApplicationAreaSize(ServiceCtx context)
         public ResultCode GetApplicationAreaSize(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(23)] // 3.0.0+
         [Command(23)] // 3.0.0+
@@ -334,7 +334,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
         // RecreateApplicationArea(bytes<8, 4>, u32, buffer<unknown, 5>)
         // RecreateApplicationArea(bytes<8, 4>, u32, buffer<unknown, 5>)
         public ResultCode RecreateApplicationArea(ServiceCtx context)
         public ResultCode RecreateApplicationArea(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
     }
     }
 }
 }

+ 15 - 6
Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs

@@ -11,6 +11,9 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
         private KEvent _event0;
         private KEvent _event0;
         private KEvent _event1;
         private KEvent _event1;
 
 
+        private int _event0Handle;
+        private int _event1Handle;
+
         private uint _version;
         private uint _version;
 
 
         public IRequest(Horizon system, uint version)
         public IRequest(Horizon system, uint version)
@@ -50,17 +53,23 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
         // GetSystemEventReadableHandles() -> (handle<copy>, handle<copy>)
         // GetSystemEventReadableHandles() -> (handle<copy>, handle<copy>)
         public ResultCode GetSystemEventReadableHandles(ServiceCtx context)
         public ResultCode GetSystemEventReadableHandles(ServiceCtx context)
         {
         {
-            if (context.Process.HandleTable.GenerateHandle(_event0.ReadableEvent, out int handle0) != KernelResult.Success)
+            if (_event0Handle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(_event0.ReadableEvent, out _event0Handle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            if (context.Process.HandleTable.GenerateHandle(_event1.ReadableEvent, out int handle1) != KernelResult.Success)
+            if (_event1Handle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(_event1.ReadableEvent, out _event1Handle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle0, handle1);
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_event0Handle, _event1Handle);
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }
@@ -107,7 +116,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
                 return ResultCode.Unknown180;
                 return ResultCode.Unknown180;
             }
             }
 
 
-            // Returns appletId, libraryAppletMode, outSize and a buffer. 
+            // Returns appletId, libraryAppletMode, outSize and a buffer.
             // Returned applet ids- (0x19, 0xf, 0xe)
             // Returned applet ids- (0x19, 0xf, 0xe)
             // libraryAppletMode seems to be 0 for all applets supported.
             // libraryAppletMode seems to be 0 for all applets supported.
 
 

+ 8 - 3
Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessor.cs

@@ -11,6 +11,8 @@ namespace Ryujinx.HLE.HOS.Services.Nim.ShopServiceAccessServerInterface.ShopServ
     {
     {
         private readonly KEvent _event;
         private readonly KEvent _event;
 
 
+        private int _eventHandle;
+
         public IShopServiceAccessor(Horizon system)
         public IShopServiceAccessor(Horizon system)
         {
         {
             _event = new KEvent(system.KernelContext);
             _event = new KEvent(system.KernelContext);
@@ -22,12 +24,15 @@ namespace Ryujinx.HLE.HOS.Services.Nim.ShopServiceAccessServerInterface.ShopServ
         {
         {
             MakeObject(context, new IShopServiceAsync());
             MakeObject(context, new IShopServiceAsync());
 
 
-            if (context.Process.HandleTable.GenerateHandle(_event.ReadableEvent, out int handle) != KernelResult.Success)
+            if (_eventHandle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(_event.ReadableEvent, out _eventHandle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_eventHandle);
 
 
             Logger.Stub?.PrintStub(LogClass.ServiceNim);
             Logger.Stub?.PrintStub(LogClass.ServiceNim);
 
 

+ 11 - 6
Ryujinx.HLE/HOS/Services/Ns/IAddOnContentManager.cs

@@ -9,7 +9,9 @@ namespace Ryujinx.HLE.HOS.Services.Ns
     [Service("aoc:u")]
     [Service("aoc:u")]
     class IAddOnContentManager : IpcService
     class IAddOnContentManager : IpcService
     {
     {
-        KEvent _addOnContentListChangedEvent;
+        private readonly KEvent _addOnContentListChangedEvent;
+
+        private int _addOnContentListChangedEventHandle;
 
 
         public IAddOnContentManager(ServiceCtx context)
         public IAddOnContentManager(ServiceCtx context)
         {
         {
@@ -22,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns
         {
         {
             long pid = context.Process.Pid;
             long pid = context.Process.Pid;
 
 
-            // Official code checks ApplicationControlProperty.RuntimeAddOnContentInstall 
+            // Official code checks ApplicationControlProperty.RuntimeAddOnContentInstall
             // if true calls ns:am ListAvailableAddOnContent again to get updated count
             // if true calls ns:am ListAvailableAddOnContent again to get updated count
 
 
             byte runtimeAddOnContentInstall = context.Device.Application.ControlData.Value.RuntimeAddOnContentInstall;
             byte runtimeAddOnContentInstall = context.Device.Application.ControlData.Value.RuntimeAddOnContentInstall;
@@ -135,12 +137,15 @@ namespace Ryujinx.HLE.HOS.Services.Ns
         {
         {
             // Official code seems to make an internal call to ns:am Cmd 84 GetDynamicCommitEvent()
             // Official code seems to make an internal call to ns:am Cmd 84 GetDynamicCommitEvent()
 
 
-            if (context.Process.HandleTable.GenerateHandle(_addOnContentListChangedEvent.ReadableEvent, out int handle) != KernelResult.Success)
+            if (_addOnContentListChangedEventHandle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(_addOnContentListChangedEvent.ReadableEvent, out _addOnContentListChangedEventHandle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_addOnContentListChangedEventHandle);
 
 
             Logger.Stub?.PrintStub(LogClass.ServiceNs);
             Logger.Stub?.PrintStub(LogClass.ServiceNs);
 
 
@@ -148,7 +153,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns
         }
         }
 
 
 
 
-        [Command(9)] // [10.0.0+] 
+        [Command(9)] // [10.0.0+]
         // GetAddOnContentLostErrorCode() -> u64
         // GetAddOnContentLostErrorCode() -> u64
         public ResultCode GetAddOnContentLostErrorCode(ServiceCtx context)
         public ResultCode GetAddOnContentLostErrorCode(ServiceCtx context)
         {
         {

+ 35 - 32
Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs

@@ -4,7 +4,6 @@ using Ryujinx.Cpu;
 using Ryujinx.HLE.Exceptions;
 using Ryujinx.HLE.Exceptions;
 using Ryujinx.HLE.HOS.Ipc;
 using Ryujinx.HLE.HOS.Ipc;
 using Ryujinx.HLE.HOS.Kernel.Memory;
 using Ryujinx.HLE.HOS.Kernel.Memory;
-using Ryujinx.HLE.HOS.Kernel.Process;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel;
@@ -12,6 +11,7 @@ using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
 using Ryujinx.HLE.HOS.Services.Nv.Types;
 using Ryujinx.HLE.HOS.Services.Nv.Types;
+using Ryujinx.Memory;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Reflection;
 using System.Reflection;
@@ -27,47 +27,45 @@ namespace Ryujinx.HLE.HOS.Services.Nv
         private static Dictionary<string, Type> _deviceFileRegistry =
         private static Dictionary<string, Type> _deviceFileRegistry =
                    new Dictionary<string, Type>()
                    new Dictionary<string, Type>()
         {
         {
-                       { "/dev/nvmap",           typeof(NvMapDeviceFile)         },
-                       { "/dev/nvhost-ctrl",     typeof(NvHostCtrlDeviceFile)    },
-                       { "/dev/nvhost-ctrl-gpu", typeof(NvHostCtrlGpuDeviceFile) },
-                       { "/dev/nvhost-as-gpu",   typeof(NvHostAsGpuDeviceFile)   },
-                       { "/dev/nvhost-gpu",      typeof(NvHostGpuDeviceFile)     },
-                     //{ "/dev/nvhost-msenc",    typeof(NvHostChannelDeviceFile) },
-                       { "/dev/nvhost-nvdec",    typeof(NvHostChannelDeviceFile) },
-                     //{ "/dev/nvhost-nvjpg",    typeof(NvHostChannelDeviceFile) },
-                       { "/dev/nvhost-vic",      typeof(NvHostChannelDeviceFile) },
-                     //{ "/dev/nvhost-display",  typeof(NvHostChannelDeviceFile) },
+            { "/dev/nvmap",           typeof(NvMapDeviceFile)         },
+            { "/dev/nvhost-ctrl",     typeof(NvHostCtrlDeviceFile)    },
+            { "/dev/nvhost-ctrl-gpu", typeof(NvHostCtrlGpuDeviceFile) },
+            { "/dev/nvhost-as-gpu",   typeof(NvHostAsGpuDeviceFile)   },
+            { "/dev/nvhost-gpu",      typeof(NvHostGpuDeviceFile)     },
+            //{ "/dev/nvhost-msenc",    typeof(NvHostChannelDeviceFile) },
+            { "/dev/nvhost-nvdec",    typeof(NvHostChannelDeviceFile) },
+            //{ "/dev/nvhost-nvjpg",    typeof(NvHostChannelDeviceFile) },
+            { "/dev/nvhost-vic",      typeof(NvHostChannelDeviceFile) },
+            //{ "/dev/nvhost-display",  typeof(NvHostChannelDeviceFile) },
         };
         };
 
 
         private static IdDictionary _deviceFileIdRegistry = new IdDictionary();
         private static IdDictionary _deviceFileIdRegistry = new IdDictionary();
 
 
-        private KProcess _owner;
+        private IVirtualMemoryManager _clientMemory;
+        private long _owner;
 
 
         private bool _transferMemInitialized = false;
         private bool _transferMemInitialized = false;
 
 
-        public INvDrvServices(ServiceCtx context) : base(new ServerBase("NvservicesServer"))
+        public INvDrvServices(ServiceCtx context) : base(new ServerBase(context.Device.System.KernelContext, "NvservicesServer"))
         {
         {
-            _owner = null;
+            _owner = 0;
         }
         }
 
 
         private int Open(ServiceCtx context, string path)
         private int Open(ServiceCtx context, string path)
         {
         {
-            if (context.Process == _owner)
+            if (_deviceFileRegistry.TryGetValue(path, out Type deviceFileClass))
             {
             {
-                if (_deviceFileRegistry.TryGetValue(path, out Type deviceFileClass))
-                {
-                    ConstructorInfo constructor = deviceFileClass.GetConstructor(new Type[] { typeof(ServiceCtx) });
+                ConstructorInfo constructor = deviceFileClass.GetConstructor(new Type[] { typeof(ServiceCtx), typeof(IVirtualMemoryManager), typeof(long) });
 
 
-                    NvDeviceFile deviceFile = (NvDeviceFile)constructor.Invoke(new object[] { context });
+                NvDeviceFile deviceFile = (NvDeviceFile)constructor.Invoke(new object[] { context, _clientMemory, _owner });
 
 
-                    deviceFile.Path = path;
+                deviceFile.Path = path;
 
 
-                    return _deviceFileIdRegistry.Add(deviceFile);
-                }
-                else
-                {
-                    Logger.Warning?.Print(LogClass.ServiceNv, $"Cannot find file device \"{path}\"!");
-                }
+                return _deviceFileIdRegistry.Add(deviceFile);
+            }
+            else
+            {
+                Logger.Warning?.Print(LogClass.ServiceNv, $"Cannot find file device \"{path}\"!");
             }
             }
 
 
             return -1;
             return -1;
@@ -150,7 +148,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
                 return NvResult.NotImplemented;
                 return NvResult.NotImplemented;
             }
             }
 
 
-            if (deviceFile.Owner.Pid != _owner.Pid)
+            if (deviceFile.Owner != _owner)
             {
             {
                 return NvResult.AccessDenied;
                 return NvResult.AccessDenied;
             }
             }
@@ -160,7 +158,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
 
 
         private NvResult EnsureInitialized()
         private NvResult EnsureInitialized()
         {
         {
-            if (_owner == null)
+            if (_owner == 0)
             {
             {
                 Logger.Warning?.Print(LogClass.ServiceNv, "INvDrvServices is not initialized!");
                 Logger.Warning?.Print(LogClass.ServiceNv, "INvDrvServices is not initialized!");
 
 
@@ -229,8 +227,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv
             if (errorCode == NvResult.Success)
             if (errorCode == NvResult.Success)
             {
             {
                 long pathPtr = context.Request.SendBuff[0].Position;
                 long pathPtr = context.Request.SendBuff[0].Position;
+                long pathSize = context.Request.SendBuff[0].Size;
 
 
-                string path = MemoryHelper.ReadAsciiString(context.Memory, pathPtr);
+                string path = MemoryHelper.ReadAsciiString(context.Memory, pathPtr, pathSize);
 
 
                 fd = Open(context, path);
                 fd = Open(context, path);
 
 
@@ -322,7 +321,11 @@ namespace Ryujinx.HLE.HOS.Services.Nv
             // TODO: When transfer memory will be implemented, this could be removed.
             // TODO: When transfer memory will be implemented, this could be removed.
             _transferMemInitialized = true;
             _transferMemInitialized = true;
 
 
-            _owner = context.Process;
+            int clientHandle = context.Request.HandleDesc.ToCopy[0];
+
+            _clientMemory = context.Process.HandleTable.GetKProcess(clientHandle).CpuMemory;
+
+            context.Device.System.KernelContext.Syscall.GetProcessId(clientHandle, out _owner);
 
 
             context.ResponseData.Write((uint)NvResult.Success);
             context.ResponseData.Write((uint)NvResult.Success);
 
 
@@ -425,7 +428,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
         // ForceSetClientPid(u64) -> u32 error_code
         // ForceSetClientPid(u64) -> u32 error_code
         public ResultCode ForceSetClientPid(ServiceCtx context)
         public ResultCode ForceSetClientPid(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(8)]
         [Command(8)]
@@ -452,7 +455,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
         // InitializeDevtools(u32, handle<copy>) -> u32 error_code;
         // InitializeDevtools(u32, handle<copy>) -> u32 error_code;
         public ResultCode InitializeDevtools(ServiceCtx context)
         public ResultCode InitializeDevtools(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(11)] // 3.0.0+
         [Command(11)] // 3.0.0+

+ 3 - 4
Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvDeviceFile.cs

@@ -1,6 +1,5 @@
 using Ryujinx.Common.Logging;
 using Ryujinx.Common.Logging;
 using Ryujinx.HLE.HOS.Kernel.Memory;
 using Ryujinx.HLE.HOS.Kernel.Memory;
-using Ryujinx.HLE.HOS.Kernel.Process;
 using System;
 using System;
 using System.Diagnostics;
 using System.Diagnostics;
 using System.Reflection;
 using System.Reflection;
@@ -12,14 +11,14 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices
     abstract class NvDeviceFile
     abstract class NvDeviceFile
     {
     {
         public readonly ServiceCtx Context;
         public readonly ServiceCtx Context;
-        public readonly KProcess   Owner;
+        public readonly long       Owner;
 
 
         public string Path;
         public string Path;
 
 
-        public NvDeviceFile(ServiceCtx context)
+        public NvDeviceFile(ServiceCtx context, long owner)
         {
         {
             Context = context;
             Context = context;
-            Owner   = context.Process;
+            Owner   = owner;
         }
         }
 
 
         public virtual NvInternalResult QueryEvent(out int eventHandle, uint eventId)
         public virtual NvInternalResult QueryEvent(out int eventHandle, uint eventId)

+ 2 - 1
Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs

@@ -3,6 +3,7 @@ using Ryujinx.Graphics.Gpu.Memory;
 using Ryujinx.HLE.HOS.Kernel.Process;
 using Ryujinx.HLE.HOS.Kernel.Process;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu.Types;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu.Types;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
+using Ryujinx.Memory;
 using System;
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Concurrent;
 
 
@@ -12,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu
     {
     {
         private static ConcurrentDictionary<KProcess, AddressSpaceContext> _addressSpaceContextRegistry = new ConcurrentDictionary<KProcess, AddressSpaceContext>();
         private static ConcurrentDictionary<KProcess, AddressSpaceContext> _addressSpaceContextRegistry = new ConcurrentDictionary<KProcess, AddressSpaceContext>();
 
 
-        public NvHostAsGpuDeviceFile(ServiceCtx context) : base(context) { }
+        public NvHostAsGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner) { }
 
 
         public override NvInternalResult Ioctl(NvIoctl command, Span<byte> arguments)
         public override NvInternalResult Ioctl(NvIoctl command, Span<byte> arguments)
         {
         {

+ 5 - 4
Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs

@@ -5,6 +5,7 @@ using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel.Types;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
 using Ryujinx.HLE.HOS.Services.Nv.Types;
 using Ryujinx.HLE.HOS.Services.Nv.Types;
+using Ryujinx.Memory;
 using System;
 using System;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
@@ -19,9 +20,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
         private uint _submitTimeout;
         private uint _submitTimeout;
         private uint _timeslice;
         private uint _timeslice;
 
 
-        private Switch _device;
+        private readonly Switch _device;
 
 
-        private Cpu.MemoryManager _memory;
+        private readonly IVirtualMemoryManager _memory;
 
 
         public enum ResourcePolicy
         public enum ResourcePolicy
         {
         {
@@ -37,10 +38,10 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
 
 
         private NvFence _channelSyncpoint;
         private NvFence _channelSyncpoint;
 
 
-        public NvHostChannelDeviceFile(ServiceCtx context) : base(context)
+        public NvHostChannelDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner)
         {
         {
             _device        = context.Device;
             _device        = context.Device;
-            _memory        = context.Memory;
+            _memory        = memory;
             _timeout       = 3000;
             _timeout       = 3000;
             _submitTimeout = 0;
             _submitTimeout = 0;
             _timeslice     = 0;
             _timeslice     = 0;

+ 3 - 2
Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostGpuDeviceFile.cs

@@ -1,6 +1,7 @@
 using Ryujinx.HLE.HOS.Kernel.Common;
 using Ryujinx.HLE.HOS.Kernel.Common;
 using Ryujinx.HLE.HOS.Kernel.Threading;
 using Ryujinx.HLE.HOS.Kernel.Threading;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel.Types;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel.Types;
+using Ryujinx.Memory;
 using System;
 using System;
 
 
 namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
 namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
@@ -11,7 +12,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
         private KEvent _smExceptionBptPauseReportEvent;
         private KEvent _smExceptionBptPauseReportEvent;
         private KEvent _errorNotifierEvent;
         private KEvent _errorNotifierEvent;
 
 
-        public NvHostGpuDeviceFile(ServiceCtx context) : base(context)
+        public NvHostGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, memory, owner)
         {
         {
             _smExceptionBptIntReportEvent   = new KEvent(context.Device.System.KernelContext);
             _smExceptionBptIntReportEvent   = new KEvent(context.Device.System.KernelContext);
             _smExceptionBptPauseReportEvent = new KEvent(context.Device.System.KernelContext);
             _smExceptionBptPauseReportEvent = new KEvent(context.Device.System.KernelContext);
@@ -55,7 +56,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
 
 
             if (targetEvent != null)
             if (targetEvent != null)
             {
             {
-                if (Owner.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != KernelResult.Success)
+                if (Context.Process.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != KernelResult.Success)
                 {
                 {
                     throw new InvalidOperationException("Out of handles!");
                     throw new InvalidOperationException("Out of handles!");
                 }
                 }

+ 3 - 3
Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs

@@ -5,7 +5,7 @@ using Ryujinx.HLE.HOS.Kernel.Threading;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl.Types;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl.Types;
 using Ryujinx.HLE.HOS.Services.Nv.Types;
 using Ryujinx.HLE.HOS.Services.Nv.Types;
 using Ryujinx.HLE.HOS.Services.Settings;
 using Ryujinx.HLE.HOS.Services.Settings;
-
+using Ryujinx.Memory;
 using System;
 using System;
 using System.Text;
 using System.Text;
 using System.Threading;
 using System.Threading;
@@ -20,7 +20,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl
         private Switch        _device;
         private Switch        _device;
         private NvHostEvent[] _events;
         private NvHostEvent[] _events;
 
 
-        public NvHostCtrlDeviceFile(ServiceCtx context) : base(context)
+        public NvHostCtrlDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner)
         {
         {
             if (NxSettings.Settings.TryGetValue("nv!rmos_set_production_mode", out object productionModeSetting))
             if (NxSettings.Settings.TryGetValue("nv!rmos_set_production_mode", out object productionModeSetting))
             {
             {
@@ -126,7 +126,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl
 
 
             if (targetEvent != null)
             if (targetEvent != null)
             {
             {
-                if (Owner.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != KernelResult.Success)
+                if (Context.Process.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != KernelResult.Success)
                 {
                 {
                     throw new InvalidOperationException("Out of handles!");
                     throw new InvalidOperationException("Out of handles!");
                 }
                 }

+ 3 - 2
Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrlGpu/NvHostCtrlGpuDeviceFile.cs

@@ -2,6 +2,7 @@
 using Ryujinx.HLE.HOS.Kernel.Common;
 using Ryujinx.HLE.HOS.Kernel.Common;
 using Ryujinx.HLE.HOS.Kernel.Threading;
 using Ryujinx.HLE.HOS.Kernel.Threading;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu.Types;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu.Types;
+using Ryujinx.Memory;
 using System;
 using System;
 using System.Diagnostics;
 using System.Diagnostics;
 
 
@@ -15,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu
         private KEvent _errorEvent;
         private KEvent _errorEvent;
         private KEvent _unknownEvent;
         private KEvent _unknownEvent;
 
 
-        public NvHostCtrlGpuDeviceFile(ServiceCtx context) : base(context)
+        public NvHostCtrlGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner)
         {
         {
             _errorEvent   = new KEvent(context.Device.System.KernelContext);
             _errorEvent   = new KEvent(context.Device.System.KernelContext);
             _unknownEvent = new KEvent(context.Device.System.KernelContext);
             _unknownEvent = new KEvent(context.Device.System.KernelContext);
@@ -98,7 +99,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu
 
 
             if (targetEvent != null)
             if (targetEvent != null)
             {
             {
-                if (Owner.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != KernelResult.Success)
+                if (Context.Process.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != KernelResult.Success)
                 {
                 {
                     throw new InvalidOperationException("Out of handles!");
                     throw new InvalidOperationException("Out of handles!");
                 }
                 }

+ 12 - 12
Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvMap/NvMapDeviceFile.cs

@@ -1,7 +1,7 @@
 using Ryujinx.Common;
 using Ryujinx.Common;
 using Ryujinx.Common.Logging;
 using Ryujinx.Common.Logging;
 using Ryujinx.Graphics.Gpu.Memory;
 using Ryujinx.Graphics.Gpu.Memory;
-using Ryujinx.HLE.HOS.Kernel.Process;
+using Ryujinx.Memory;
 using System;
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Concurrent;
 
 
@@ -11,9 +11,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
     {
     {
         private const int FlagNotFreedYet = 1;
         private const int FlagNotFreedYet = 1;
 
 
-        private static ConcurrentDictionary<KProcess, IdDictionary> _maps = new ConcurrentDictionary<KProcess, IdDictionary>();
+        private static ConcurrentDictionary<long, IdDictionary> _maps = new ConcurrentDictionary<long, IdDictionary>();
 
 
-        public NvMapDeviceFile(ServiceCtx context) : base(context)
+        public NvMapDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner)
         {
         {
             IdDictionary dict = _maps.GetOrAdd(Owner, (key) => new IdDictionary());
             IdDictionary dict = _maps.GetOrAdd(Owner, (key) => new IdDictionary());
 
 
@@ -244,9 +244,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
             return dict.Add(map);
             return dict.Add(map);
         }
         }
 
 
-        private static bool DeleteMapWithHandle(KProcess process, int handle)
+        private static bool DeleteMapWithHandle(long pid, int handle)
         {
         {
-            if (_maps.TryGetValue(process, out IdDictionary dict))
+            if (_maps.TryGetValue(pid, out IdDictionary dict))
             {
             {
                 return dict.Delete(handle) != null;
                 return dict.Delete(handle) != null;
             }
             }
@@ -254,14 +254,14 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
             return false;
             return false;
         }
         }
 
 
-        public static void IncrementMapRefCount(KProcess process, int handle, bool allowHandleZero = false)
+        public static void IncrementMapRefCount(long pid, int handle, bool allowHandleZero = false)
         {
         {
-            GetMapFromHandle(process, handle, allowHandleZero)?.IncrementRefCount();
+            GetMapFromHandle(pid, handle, allowHandleZero)?.IncrementRefCount();
         }
         }
 
 
-        public static bool DecrementMapRefCount(KProcess process, int handle)
+        public static bool DecrementMapRefCount(long pid, int handle)
         {
         {
-            NvMapHandle map = GetMapFromHandle(process, handle, false);
+            NvMapHandle map = GetMapFromHandle(pid, handle, false);
 
 
             if (map == null)
             if (map == null)
             {
             {
@@ -270,7 +270,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
 
 
             if (map.DecrementRefCount() <= 0)
             if (map.DecrementRefCount() <= 0)
             {
             {
-                DeleteMapWithHandle(process, handle);
+                DeleteMapWithHandle(pid, handle);
 
 
                 Logger.Info?.Print(LogClass.ServiceNv, $"Deleted map {handle}!");
                 Logger.Info?.Print(LogClass.ServiceNv, $"Deleted map {handle}!");
 
 
@@ -282,9 +282,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
             }
             }
         }
         }
 
 
-        public static NvMapHandle GetMapFromHandle(KProcess process, int handle, bool allowHandleZero = false)
+        public static NvMapHandle GetMapFromHandle(long pid, int handle, bool allowHandleZero = false)
         {
         {
-            if ((allowHandleZero || handle != 0) && _maps.TryGetValue(process, out IdDictionary dict))
+            if ((allowHandleZero || handle != 0) && _maps.TryGetValue(pid, out IdDictionary dict))
             {
             {
                 return dict.GetData<NvMapHandle>(handle);
                 return dict.GetData<NvMapHandle>(handle);
             }
             }

+ 19 - 18
Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs

@@ -53,7 +53,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
                 return ResultCode.InvalidAddress;
                 return ResultCode.InvalidAddress;
             }
             }
 
 
-            StructReader reader = new StructReader(context.Memory, nrrAddress);
+            StructReader reader = new StructReader(_owner.CpuMemory, nrrAddress);
             NrrHeader    header = reader.Read<NrrHeader>();
             NrrHeader    header = reader.Read<NrrHeader>();
 
 
             if (header.Magic != NrrMagic)
             if (header.Magic != NrrMagic)
@@ -71,7 +71,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
             {
             {
                 byte[] temp = new byte[0x20];
                 byte[] temp = new byte[0x20];
 
 
-                context.Memory.Read((ulong)(nrrAddress + header.HashOffset + (i * 0x20)), temp);
+                _owner.CpuMemory.Read((ulong)(nrrAddress + header.HashOffset + (i * 0x20)), temp);
 
 
                 hashes.Add(temp);
                 hashes.Add(temp);
             }
             }
@@ -131,8 +131,8 @@ namespace Ryujinx.HLE.HOS.Services.Ro
                 return ResultCode.InvalidAddress;
                 return ResultCode.InvalidAddress;
             }
             }
 
 
-            uint magic       = context.Memory.Read<uint>(nroAddress + 0x10);
-            uint nroFileSize = context.Memory.Read<uint>(nroAddress + 0x18);
+            uint magic       = _owner.CpuMemory.Read<uint>(nroAddress + 0x10);
+            uint nroFileSize = _owner.CpuMemory.Read<uint>(nroAddress + 0x18);
 
 
             if (magic != NroMagic || nroSize != nroFileSize)
             if (magic != NroMagic || nroSize != nroFileSize)
             {
             {
@@ -141,7 +141,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
 
 
             byte[] nroData = new byte[nroSize];
             byte[] nroData = new byte[nroSize];
 
 
-            context.Memory.Read(nroAddress, nroData);
+            _owner.CpuMemory.Read(nroAddress, nroData);
 
 
             byte[] nroHash = null;
             byte[] nroHash = null;
 
 
@@ -176,7 +176,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
             // Check if everything is contiguous.
             // Check if everything is contiguous.
             if (nro.RoOffset   != nro.TextOffset + nro.Text.Length ||
             if (nro.RoOffset   != nro.TextOffset + nro.Text.Length ||
                 nro.DataOffset != nro.RoOffset   + nro.Ro.Length   ||
                 nro.DataOffset != nro.RoOffset   + nro.Ro.Length   ||
-                nroFileSize           != nro.DataOffset + nro.Data.Length)
+                nroFileSize    != nro.DataOffset + nro.Data.Length)
             {
             {
                 return ResultCode.InvalidNro;
                 return ResultCode.InvalidNro;
             }
             }
@@ -337,21 +337,21 @@ namespace Ryujinx.HLE.HOS.Services.Ro
 
 
             KernelResult result;
             KernelResult result;
 
 
-            result = process.MemoryManager.SetProcessMemoryPermission(textStart, roStart - textStart, MemoryPermission.ReadAndExecute);
+            result = process.MemoryManager.SetProcessMemoryPermission(textStart, roStart - textStart, KMemoryPermission.ReadAndExecute);
 
 
             if (result != KernelResult.Success)
             if (result != KernelResult.Success)
             {
             {
                 return result;
                 return result;
             }
             }
 
 
-            result = process.MemoryManager.SetProcessMemoryPermission(roStart, dataStart - roStart, MemoryPermission.Read);
+            result = process.MemoryManager.SetProcessMemoryPermission(roStart, dataStart - roStart, KMemoryPermission.Read);
 
 
             if (result != KernelResult.Success)
             if (result != KernelResult.Success)
             {
             {
                 return result;
                 return result;
             }
             }
 
 
-            return process.MemoryManager.SetProcessMemoryPermission(dataStart, bssEnd - dataStart, MemoryPermission.ReadAndWrite);
+            return process.MemoryManager.SetProcessMemoryPermission(dataStart, bssEnd - dataStart, KMemoryPermission.ReadAndWrite);
         }
         }
 
 
         private ResultCode RemoveNrrInfo(long nrrAddress)
         private ResultCode RemoveNrrInfo(long nrrAddress)
@@ -420,9 +420,9 @@ namespace Ryujinx.HLE.HOS.Services.Ro
             return (ResultCode)result;
             return (ResultCode)result;
         }
         }
 
 
-        private ResultCode IsInitialized(KProcess process)
+        private ResultCode IsInitialized(long pid)
         {
         {
-            if (_owner != null && _owner.Pid == process.Pid)
+            if (_owner != null && _owner.Pid == pid)
             {
             {
                 return ResultCode.Success;
                 return ResultCode.Success;
             }
             }
@@ -434,7 +434,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
         // LoadNro(u64, u64, u64, u64, u64, pid) -> u64
         // LoadNro(u64, u64, u64, u64, u64, pid) -> u64
         public ResultCode LoadNro(ServiceCtx context)
         public ResultCode LoadNro(ServiceCtx context)
         {
         {
-            ResultCode result = IsInitialized(context.Process);
+            ResultCode result = IsInitialized(_owner.Pid);
 
 
             // Zero
             // Zero
             context.RequestData.ReadUInt64();
             context.RequestData.ReadUInt64();
@@ -454,11 +454,11 @@ namespace Ryujinx.HLE.HOS.Services.Ro
 
 
                 if (result == ResultCode.Success)
                 if (result == ResultCode.Success)
                 {
                 {
-                    result = MapNro(context.Process, info, out nroMappedAddress);
+                    result = MapNro(_owner, info, out nroMappedAddress);
 
 
                     if (result == ResultCode.Success)
                     if (result == ResultCode.Success)
                     {
                     {
-                        result = (ResultCode)SetNroMemoryPermissions(context.Process, info.Executable, nroMappedAddress);
+                        result = (ResultCode)SetNroMemoryPermissions(_owner, info.Executable, nroMappedAddress);
 
 
                         if (result == ResultCode.Success)
                         if (result == ResultCode.Success)
                         {
                         {
@@ -479,7 +479,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
         // UnloadNro(u64, u64, pid)
         // UnloadNro(u64, u64, pid)
         public ResultCode UnloadNro(ServiceCtx context)
         public ResultCode UnloadNro(ServiceCtx context)
         {
         {
-            ResultCode result = IsInitialized(context.Process);
+            ResultCode result = IsInitialized(_owner.Pid);
 
 
             // Zero
             // Zero
             context.RequestData.ReadUInt64();
             context.RequestData.ReadUInt64();
@@ -503,7 +503,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
         // LoadNrr(u64, u64, u64, pid)
         // LoadNrr(u64, u64, u64, pid)
         public ResultCode LoadNrr(ServiceCtx context)
         public ResultCode LoadNrr(ServiceCtx context)
         {
         {
-            ResultCode result = IsInitialized(context.Process);
+            ResultCode result = IsInitialized(_owner.Pid);
 
 
             // pid placeholder, zero
             // pid placeholder, zero
             context.RequestData.ReadUInt64();
             context.RequestData.ReadUInt64();
@@ -536,7 +536,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
         // UnloadNrr(u64, u64, pid)
         // UnloadNrr(u64, u64, pid)
         public ResultCode UnloadNrr(ServiceCtx context)
         public ResultCode UnloadNrr(ServiceCtx context)
         {
         {
-            ResultCode result = IsInitialized(context.Process);
+            ResultCode result = IsInitialized(_owner.Pid);
 
 
             // pid placeholder, zero
             // pid placeholder, zero
             context.RequestData.ReadUInt64();
             context.RequestData.ReadUInt64();
@@ -565,7 +565,8 @@ namespace Ryujinx.HLE.HOS.Services.Ro
                 return ResultCode.InvalidSession;
                 return ResultCode.InvalidSession;
             }
             }
 
 
-            _owner = context.Process;
+            _owner = context.Process.HandleTable.GetKProcess(context.Request.HandleDesc.ToCopy[0]);
+            context.Device.System.KernelContext.Syscall.CloseHandle(context.Request.HandleDesc.ToCopy[0]);
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }

+ 8 - 3
Ryujinx.HLE/HOS/Services/Sdb/Pl/ISharedFontManager.cs

@@ -9,6 +9,8 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pl
     [Service("pl:s")] // 9.0.0+
     [Service("pl:s")] // 9.0.0+
     class ISharedFontManager : IpcService
     class ISharedFontManager : IpcService
     {
     {
+        private int _fontSharedMemHandle;
+
         public ISharedFontManager(ServiceCtx context) { }
         public ISharedFontManager(ServiceCtx context) { }
 
 
         [Command(0)]
         [Command(0)]
@@ -63,12 +65,15 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pl
         {
         {
             context.Device.System.Font.EnsureInitialized(context.Device.System.ContentManager);
             context.Device.System.Font.EnsureInitialized(context.Device.System.ContentManager);
 
 
-            if (context.Process.HandleTable.GenerateHandle(context.Device.System.FontSharedMem, out int handle) != KernelResult.Success)
+            if (_fontSharedMemHandle == 0)
             {
             {
-                throw new InvalidOperationException("Out of handles!");
+                if (context.Process.HandleTable.GenerateHandle(context.Device.System.FontSharedMem, out _fontSharedMemHandle) != KernelResult.Success)
+                {
+                    throw new InvalidOperationException("Out of handles!");
+                }
             }
             }
 
 
-            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_fontSharedMemHandle);
 
 
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }

+ 184 - 49
Ryujinx.HLE/HOS/Services/ServerBase.cs

@@ -1,62 +1,193 @@
-using Ryujinx.Common;
 using Ryujinx.HLE.HOS.Ipc;
 using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel;
 using Ryujinx.HLE.HOS.Kernel.Common;
 using Ryujinx.HLE.HOS.Kernel.Common;
 using Ryujinx.HLE.HOS.Kernel.Ipc;
 using Ryujinx.HLE.HOS.Kernel.Ipc;
 using Ryujinx.HLE.HOS.Kernel.Process;
 using Ryujinx.HLE.HOS.Kernel.Process;
 using Ryujinx.HLE.HOS.Kernel.Threading;
 using Ryujinx.HLE.HOS.Kernel.Threading;
 using System;
 using System;
+using System.Buffers.Binary;
+using System.Collections.Generic;
 using System.IO;
 using System.IO;
+using System.Threading;
 
 
 namespace Ryujinx.HLE.HOS.Services
 namespace Ryujinx.HLE.HOS.Services
 {
 {
     class ServerBase
     class ServerBase
     {
     {
-        private struct IpcRequest
+        // Must be the maximum value used by services (highest one know is the one used by nvservices = 0x8000).
+        // Having a size that is too low will cause failures as data copy will fail if the receiving buffer is
+        // not large enough.
+        private const int PointerBufferSize = 0x8000;
+
+        private readonly static int[] DefaultCapabilities = new int[]
         {
         {
-            public Switch Device { get; }
-            public KProcess Process => Thread?.Owner;
-            public KThread Thread { get; }
-            public KClientSession Session { get; }
-            public ulong MessagePtr { get; }
-            public ulong MessageSize { get; }
-
-            public IpcRequest(Switch device, KThread thread, KClientSession session, ulong messagePtr, ulong messageSize)
-            {
-                Device = device;
-                Thread = thread;
-                Session = session;
-                MessagePtr = messagePtr;
-                MessageSize = messageSize;
-            }
+            0x030363F7,
+            0x1FFFFFCF,
+            0x207FFFEF,
+            0x47E0060F,
+            0x0048BFFF,
+            0x01007FFF
+        };
+
+        private readonly KernelContext _context;
+        private readonly KProcess _selfProcess;
+
+        private readonly List<int> _sessionHandles = new List<int>();
+        private readonly List<int> _portHandles = new List<int>();
+        private readonly Dictionary<int, IpcService> _sessions = new Dictionary<int, IpcService>();
+        private readonly Dictionary<int, IpcService> _ports = new Dictionary<int, IpcService>();
+
+        public ManualResetEvent InitDone { get; }
+        public IpcService SmObject { get; set; }
+        public string Name { get; }
+
+        public ServerBase(KernelContext context, string name)
+        {
+            InitDone = new ManualResetEvent(false);
+            Name = name;
+            _context = context;
 
 
-            public void SignalDone(KernelResult result)
-            {
-                Thread.ObjSyncResult = result;
-                Thread.Reschedule(ThreadSchedState.Running);
-            }
+            const ProcessCreationFlags flags =
+                ProcessCreationFlags.EnableAslr |
+                ProcessCreationFlags.AddressSpace64Bit |
+                ProcessCreationFlags.Is64Bit |
+                ProcessCreationFlags.PoolPartitionSystem;
+
+            ProcessCreationInfo creationInfo = new ProcessCreationInfo("Service", 1, 0, 0x8000000, 1, flags, 0, 0);
+
+            context.Syscall.CreateProcess(creationInfo, DefaultCapabilities, out int handle, null, ServerLoop);
+
+            _selfProcess = context.Scheduler.GetCurrentProcess().HandleTable.GetKProcess(handle);
+
+            context.Syscall.StartProcess(handle, 44, 3, 0x1000);
         }
         }
 
 
-        private readonly AsyncWorkQueue<IpcRequest> _ipcProcessor;
+        private void AddPort(int serverPortHandle, IpcService obj)
+        {
+            _portHandles.Add(serverPortHandle);
+            _ports.Add(serverPortHandle, obj);
+        }
 
 
-        public ServerBase(string name)
+        public void AddSessionObj(KServerSession serverSession, IpcService obj)
         {
         {
-            _ipcProcessor = new AsyncWorkQueue<IpcRequest>(Process, name);
+            _selfProcess.HandleTable.GenerateHandle(serverSession, out int serverSessionHandle);
+            AddSessionObj(serverSessionHandle, obj);
         }
         }
 
 
-        public void PushMessage(Switch device, KThread thread, KClientSession session, ulong messagePtr, ulong messageSize)
+        public void AddSessionObj(int serverSessionHandle, IpcService obj)
         {
         {
-            _ipcProcessor.Add(new IpcRequest(device, thread, session, messagePtr, messageSize));
+            _sessionHandles.Add(serverSessionHandle);
+            _sessions.Add(serverSessionHandle, obj);
         }
         }
 
 
-        private void Process(IpcRequest message)
+        private void ServerLoop()
         {
         {
-            byte[] reqData = new byte[message.MessageSize];
+            if (SmObject != null)
+            {
+                _context.Syscall.ManageNamedPort("sm:", 50, out int serverPortHandle);
+
+                AddPort(serverPortHandle, SmObject);
+
+                InitDone.Set();
+            }
+            else
+            {
+                InitDone.Dispose();
+            }
+
+            KThread thread = _context.Scheduler.GetCurrentThread();
+            ulong messagePtr = thread.TlsAddress;
+            _context.Syscall.SetHeapSize(0x200000, out ulong heapAddr);
+
+            _selfProcess.CpuMemory.Write(messagePtr + 0x0, 0);
+            _selfProcess.CpuMemory.Write(messagePtr + 0x4, 2 << 10);
+            _selfProcess.CpuMemory.Write(messagePtr + 0x8, heapAddr | ((ulong)PointerBufferSize << 48));
+
+            int replyTargetHandle = 0;
+
+            while (true)
+            {
+                int[] handles = _portHandles.ToArray();
+
+                for (int i = 0; i < handles.Length; i++)
+                {
+                    if (_context.Syscall.AcceptSession(handles[i], out int serverSessionHandle) == KernelResult.Success)
+                    {
+                        AddSessionObj(serverSessionHandle, _ports[handles[i]]);
+                    }
+                }
+
+                handles = _sessionHandles.ToArray();
+
+                var rc = _context.Syscall.ReplyAndReceive(handles, replyTargetHandle, 1000000L, out int signaledIndex);
+
+                thread.HandlePostSyscall();
+
+                if (!thread.Context.Running)
+                {
+                    break;
+                }
 
 
-            message.Process.CpuMemory.Read(message.MessagePtr, reqData);
+                replyTargetHandle = 0;
 
 
-            IpcMessage request = new IpcMessage(reqData, (long)message.MessagePtr);
+                if (rc == KernelResult.Success && signaledIndex != -1)
+                {
+                    int signaledHandle = handles[signaledIndex];
+
+                    if (Process(signaledHandle, heapAddr))
+                    {
+                        replyTargetHandle = signaledHandle;
+                    }
+                }
+                else
+                {
+                    _selfProcess.CpuMemory.Write(messagePtr + 0x0, 0);
+                    _selfProcess.CpuMemory.Write(messagePtr + 0x4, 2 << 10);
+                    _selfProcess.CpuMemory.Write(messagePtr + 0x8, heapAddr | ((ulong)PointerBufferSize << 48));
+                }
+            }
+        }
+
+        private bool Process(int serverSessionHandle, ulong recvListAddr)
+        {
+            KProcess process = _context.Scheduler.GetCurrentProcess();
+            KThread thread = _context.Scheduler.GetCurrentThread();
+            ulong messagePtr = thread.TlsAddress;
+            ulong messageSize = 0x100;
+
+            byte[] reqData = new byte[messageSize];
+
+            process.CpuMemory.Read(messagePtr, reqData);
+
+            IpcMessage request = new IpcMessage(reqData, (long)messagePtr);
             IpcMessage response = new IpcMessage();
             IpcMessage response = new IpcMessage();
 
 
+            ulong tempAddr = recvListAddr;
+            int sizesOffset = request.RawData.Length - ((request.RecvListBuff.Count * 2 + 3) & ~3);
+
+            bool noReceive = true;
+
+            for (int i = 0; i < request.ReceiveBuff.Count; i++)
+            {
+                noReceive &= (request.ReceiveBuff[i].Position == 0);
+            }
+
+            if (noReceive)
+            {
+                for (int i = 0; i < request.RecvListBuff.Count; i++)
+                {
+                    int size = BinaryPrimitives.ReadInt16LittleEndian(request.RawData.AsSpan().Slice(sizesOffset + i * 2, 2));
+
+                    response.PtrBuff.Add(new IpcPtrBuffDesc((long)tempAddr, i, size));
+
+                    request.RecvListBuff[i] = new IpcRecvListBuffDesc((long)tempAddr, size);
+
+                    tempAddr += (ulong)size;
+                }
+            }
+
+            bool shouldReply = true;
+
             using (MemoryStream raw = new MemoryStream(request.RawData))
             using (MemoryStream raw = new MemoryStream(request.RawData))
             {
             {
                 BinaryReader reqReader = new BinaryReader(raw);
                 BinaryReader reqReader = new BinaryReader(raw);
@@ -71,17 +202,16 @@ namespace Ryujinx.HLE.HOS.Services
                         BinaryWriter resWriter = new BinaryWriter(resMs);
                         BinaryWriter resWriter = new BinaryWriter(resMs);
 
 
                         ServiceCtx context = new ServiceCtx(
                         ServiceCtx context = new ServiceCtx(
-                            message.Device,
-                            message.Process,
-                            message.Process.CpuMemory,
-                            message.Thread,
-                            message.Session,
+                            _context.Device,
+                            process,
+                            process.CpuMemory,
+                            thread,
                             request,
                             request,
                             response,
                             response,
                             reqReader,
                             reqReader,
                             resWriter);
                             resWriter);
 
 
-                        message.Session.Service.CallMethod(context);
+                        _sessions[serverSessionHandle].CallMethod(context);
 
 
                         response.RawData = resMs.ToArray();
                         response.RawData = resMs.ToArray();
                     }
                     }
@@ -95,11 +225,11 @@ namespace Ryujinx.HLE.HOS.Services
                     switch (cmdId)
                     switch (cmdId)
                     {
                     {
                         case 0:
                         case 0:
-                            request = FillResponse(response, 0, message.Session.Service.ConvertToDomain());
+                            request = FillResponse(response, 0, _sessions[serverSessionHandle].ConvertToDomain());
                             break;
                             break;
 
 
                         case 3:
                         case 3:
-                            request = FillResponse(response, 0, 0x1000);
+                            request = FillResponse(response, 0, PointerBufferSize);
                             break;
                             break;
 
 
                         // TODO: Whats the difference between IpcDuplicateSession/Ex?
                         // TODO: Whats the difference between IpcDuplicateSession/Ex?
@@ -107,12 +237,11 @@ namespace Ryujinx.HLE.HOS.Services
                         case 4:
                         case 4:
                             int unknown = reqReader.ReadInt32();
                             int unknown = reqReader.ReadInt32();
 
 
-                            if (message.Process.HandleTable.GenerateHandle(message.Session, out int handle) != KernelResult.Success)
-                            {
-                                throw new InvalidOperationException("Out of handles!");
-                            }
+                            _context.Syscall.CreateSession(false, 0, out int dupServerSessionHandle, out int dupClientSessionHandle);
 
 
-                            response.HandleDesc = IpcHandleDesc.MakeMove(handle);
+                            AddSessionObj(dupServerSessionHandle, _sessions[serverSessionHandle]);
+
+                            response.HandleDesc = IpcHandleDesc.MakeMove(dupClientSessionHandle);
 
 
                             request = FillResponse(response, 0);
                             request = FillResponse(response, 0);
 
 
@@ -123,18 +252,24 @@ namespace Ryujinx.HLE.HOS.Services
                 }
                 }
                 else if (request.Type == IpcMessageType.CloseSession)
                 else if (request.Type == IpcMessageType.CloseSession)
                 {
                 {
-                    message.SignalDone(KernelResult.PortRemoteClosed);
-                    return;
+                    _context.Syscall.CloseHandle(serverSessionHandle);
+                    _sessionHandles.Remove(serverSessionHandle);
+                    IpcService service = _sessions[serverSessionHandle];
+                    if (service is IDisposable disposableObj)
+                    {
+                        disposableObj.Dispose();
+                    }
+                    _sessions.Remove(serverSessionHandle);
+                    shouldReply = false;
                 }
                 }
                 else
                 else
                 {
                 {
                     throw new NotImplementedException(request.Type.ToString());
                     throw new NotImplementedException(request.Type.ToString());
                 }
                 }
 
 
-                message.Process.CpuMemory.Write(message.MessagePtr, response.GetBytes((long)message.MessagePtr));
+                process.CpuMemory.Write(messagePtr, response.GetBytes((long)messagePtr, recvListAddr | ((ulong)PointerBufferSize << 48)));
+                return shouldReply;
             }
             }
-
-            message.SignalDone(KernelResult.Success);
         }
         }
 
 
         private static IpcMessage FillResponse(IpcMessage response, long result, params int[] values)
         private static IpcMessage FillResponse(IpcMessage response, long result, params int[] values)

+ 8 - 20
Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs

@@ -1,5 +1,6 @@
 using Ryujinx.Common.Logging;
 using Ryujinx.Common.Logging;
 using Ryujinx.HLE.HOS.Ipc;
 using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel;
 using Ryujinx.HLE.HOS.Kernel.Common;
 using Ryujinx.HLE.HOS.Kernel.Common;
 using Ryujinx.HLE.HOS.Kernel.Ipc;
 using Ryujinx.HLE.HOS.Kernel.Ipc;
 using System;
 using System;
@@ -11,18 +12,17 @@ using System.Reflection;
 
 
 namespace Ryujinx.HLE.HOS.Services.Sm
 namespace Ryujinx.HLE.HOS.Services.Sm
 {
 {
-    [Service("sm:")]
     class IUserInterface : IpcService
     class IUserInterface : IpcService
     {
     {
         private Dictionary<string, Type> _services;
         private Dictionary<string, Type> _services;
 
 
-        private ConcurrentDictionary<string, KPort> _registeredServices;
+        private readonly ConcurrentDictionary<string, KPort> _registeredServices;
 
 
         private readonly ServerBase _commonServer;
         private readonly ServerBase _commonServer;
 
 
         private bool _isInitialized;
         private bool _isInitialized;
 
 
-        public IUserInterface(ServiceCtx context = null) : base(new ServerBase("SmServer"))
+        public IUserInterface(KernelContext context)
         {
         {
             _registeredServices = new ConcurrentDictionary<string, KPort>();
             _registeredServices = new ConcurrentDictionary<string, KPort>();
 
 
@@ -31,18 +31,9 @@ namespace Ryujinx.HLE.HOS.Services.Sm
                 .Select(service => (((ServiceAttribute)service).Name, type)))
                 .Select(service => (((ServiceAttribute)service).Name, type)))
                 .ToDictionary(service => service.Name, service => service.type);
                 .ToDictionary(service => service.Name, service => service.type);
 
 
-            _commonServer = new ServerBase("CommonServer");
-        }
-
-        public static void InitializePort(Horizon system)
-        {
-            KPort port = new KPort(system.KernelContext, 256, false, 0);
-
-            port.ClientPort.SetName("sm:");
-
-            IUserInterface smService = new IUserInterface();
+            TrySetServer(new ServerBase(context, "SmServer") { SmObject = this });
 
 
-            port.ClientPort.Service = smService;
+            _commonServer = new ServerBase(context, "CommonServer");
         }
         }
 
 
         [Command(0)]
         [Command(0)]
@@ -92,16 +83,13 @@ namespace Ryujinx.HLE.HOS.Services.Sm
                         : (IpcService)Activator.CreateInstance(type, context);
                         : (IpcService)Activator.CreateInstance(type, context);
 
 
                     service.TrySetServer(_commonServer);
                     service.TrySetServer(_commonServer);
-
-                    session.ClientSession.Service = service;
+                    service.Server.AddSessionObj(session.ServerSession, service);
                 }
                 }
                 else
                 else
                 {
                 {
                     if (ServiceConfiguration.IgnoreMissingServices)
                     if (ServiceConfiguration.IgnoreMissingServices)
                     {
                     {
                         Logger.Warning?.Print(LogClass.Service, $"Missing service {name} ignored");
                         Logger.Warning?.Print(LogClass.Service, $"Missing service {name} ignored");
-
-                        session.ClientSession.Service = new DummyService(name);
                     }
                     }
                     else
                     else
                     {
                     {
@@ -142,7 +130,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm
 
 
             int maxSessions = context.RequestData.ReadInt32();
             int maxSessions = context.RequestData.ReadInt32();
 
 
-            if (name == string.Empty)
+            if (string.IsNullOrEmpty(name))
             {
             {
                 return ResultCode.InvalidName;
                 return ResultCode.InvalidName;
             }
             }
@@ -185,7 +173,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm
 
 
             int maxSessions = context.RequestData.ReadInt32();
             int maxSessions = context.RequestData.ReadInt32();
 
 
-            if (name == string.Empty)
+            if (string.IsNullOrEmpty(name))
             {
             {
                 return ResultCode.InvalidName;
                 return ResultCode.InvalidName;
             }
             }

+ 4 - 1
Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs

@@ -102,7 +102,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
 
 
         private List<BsdSocket> _sockets = new List<BsdSocket>();
         private List<BsdSocket> _sockets = new List<BsdSocket>();
 
 
-        public IClient(ServiceCtx context, bool isPrivileged)  : base(new ServerBase("BsdServer"))
+        public IClient(ServiceCtx context, bool isPrivileged) : base(new ServerBase(context.Device.System.KernelContext, "BsdServer"))
         {
         {
             _isPrivileged = isPrivileged;
             _isPrivileged = isPrivileged;
         }
         }
@@ -247,6 +247,9 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
 
 
             Logger.Stub?.PrintStub(LogClass.ServiceBsd);
             Logger.Stub?.PrintStub(LogClass.ServiceBsd);
 
 
+            // Close transfer memory immediately as we don't use it.
+            context.Device.System.KernelContext.Syscall.CloseHandle(context.Request.HandleDesc.ToCopy[0]);
+
             return ResultCode.Success;
             return ResultCode.Success;
         }
         }
 
 

+ 10 - 10
Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs

@@ -118,14 +118,14 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd
         // ImportSettings(u32, buffer<unknown, 5>) -> buffer<unknown, 6>
         // ImportSettings(u32, buffer<unknown, 5>) -> buffer<unknown, 6>
         public ResultCode ImportSettings(ServiceCtx context)
         public ResultCode ImportSettings(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(15)]
         [Command(15)]
         // Unknown(bytes<1>)
         // Unknown(bytes<1>)
         public ResultCode Unknown(ServiceCtx context)
         public ResultCode Unknown(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(20)]
         [Command(20)]
@@ -164,49 +164,49 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd
         // GetNasServiceSetting(buffer<unknown<0x10>, 0x15>) -> buffer<unknown<0x108>, 0x16>
         // GetNasServiceSetting(buffer<unknown<0x10>, 0x15>) -> buffer<unknown<0x108>, 0x16>
         public ResultCode GetNasServiceSetting(ServiceCtx context)
         public ResultCode GetNasServiceSetting(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(31)]
         [Command(31)]
         // GetNasServiceSettingEx(buffer<unknown<0x10>, 0x15>) -> (u32, buffer<unknown<0x108>, 0x16>)
         // GetNasServiceSettingEx(buffer<unknown<0x10>, 0x15>) -> (u32, buffer<unknown<0x108>, 0x16>)
         public ResultCode GetNasServiceSettingEx(ServiceCtx context)
         public ResultCode GetNasServiceSettingEx(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(40)]
         [Command(40)]
         // GetNasRequestFqdn() -> buffer<unknown<0x100>, 0x16>
         // GetNasRequestFqdn() -> buffer<unknown<0x100>, 0x16>
         public ResultCode GetNasRequestFqdn(ServiceCtx context)
         public ResultCode GetNasRequestFqdn(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(41)]
         [Command(41)]
         // GetNasRequestFqdnEx() -> (u32, buffer<unknown<0x100>, 0x16>)
         // GetNasRequestFqdnEx() -> (u32, buffer<unknown<0x100>, 0x16>)
         public ResultCode GetNasRequestFqdnEx(ServiceCtx context)
         public ResultCode GetNasRequestFqdnEx(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(42)]
         [Command(42)]
         // GetNasApiFqdn() -> buffer<unknown<0x100>, 0x16>
         // GetNasApiFqdn() -> buffer<unknown<0x100>, 0x16>
         public ResultCode GetNasApiFqdn(ServiceCtx context)
         public ResultCode GetNasApiFqdn(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(43)]
         [Command(43)]
         // GetNasApiFqdnEx() -> (u32, buffer<unknown<0x100>, 0x16>)
         // GetNasApiFqdnEx() -> (u32, buffer<unknown<0x100>, 0x16>)
         public ResultCode GetNasApiFqdnEx(ServiceCtx context)
         public ResultCode GetNasApiFqdnEx(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(50)]
         [Command(50)]
         // GetCurrentSetting() -> buffer<unknown<0x12bf0>, 0x16>
         // GetCurrentSetting() -> buffer<unknown<0x12bf0>, 0x16>
         public ResultCode GetCurrentSetting(ServiceCtx context)
         public ResultCode GetCurrentSetting(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(60)]
         [Command(60)]
@@ -262,7 +262,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd
         // IsChangeEnvironmentIdentifierDisabled() -> bytes<1>
         // IsChangeEnvironmentIdentifierDisabled() -> bytes<1>
         public ResultCode IsChangeEnvironmentIdentifierDisabled(ServiceCtx context)
         public ResultCode IsChangeEnvironmentIdentifierDisabled(ServiceCtx context)
         {
         {
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
     }
     }
 }
 }

+ 6 - 6
Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueue.cs

@@ -1,15 +1,15 @@
-using Ryujinx.HLE.HOS.Kernel.Process;
-
-namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
+namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
 {
 {
-    class BufferQueue
+    static class BufferQueue
     {
     {
-        public static void CreateBufferQueue(Switch device, KProcess process, out BufferQueueProducer producer, out BufferQueueConsumer consumer)
+        public static BufferQueueCore CreateBufferQueue(Switch device, long pid, out BufferQueueProducer producer, out BufferQueueConsumer consumer)
         {
         {
-            BufferQueueCore core = new BufferQueueCore(device, process);
+            BufferQueueCore core = new BufferQueueCore(device, pid);
 
 
             producer = new BufferQueueProducer(core);
             producer = new BufferQueueProducer(core);
             consumer = new BufferQueueConsumer(core);
             consumer = new BufferQueueConsumer(core);
+
+            return core;
         }
         }
     }
     }
 }
 }

+ 39 - 6
Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueCore.cs

@@ -1,5 +1,5 @@
 using Ryujinx.Common.Logging;
 using Ryujinx.Common.Logging;
-using Ryujinx.HLE.HOS.Kernel.Process;
+using Ryujinx.HLE.HOS.Kernel;
 using Ryujinx.HLE.HOS.Kernel.Threading;
 using Ryujinx.HLE.HOS.Kernel.Threading;
 using Ryujinx.HLE.HOS.Services.SurfaceFlinger.Types;
 using Ryujinx.HLE.HOS.Services.SurfaceFlinger.Types;
 using System;
 using System;
@@ -40,11 +40,13 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
         private KEvent _waitBufferFreeEvent;
         private KEvent _waitBufferFreeEvent;
         private KEvent _frameAvailableEvent;
         private KEvent _frameAvailableEvent;
 
 
-        public KProcess Owner { get; }
+        public long Owner { get; }
+
+        public bool Active { get; private set; }
 
 
         public const int BufferHistoryArraySize = 8;
         public const int BufferHistoryArraySize = 8;
 
 
-        public BufferQueueCore(Switch device, KProcess process)
+        public BufferQueueCore(Switch device, long pid)
         {
         {
             Slots                    = new BufferSlotArray();
             Slots                    = new BufferSlotArray();
             IsAbandoned              = false;
             IsAbandoned              = false;
@@ -70,7 +72,9 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
             _waitBufferFreeEvent  = new KEvent(device.System.KernelContext);
             _waitBufferFreeEvent  = new KEvent(device.System.KernelContext);
             _frameAvailableEvent = new KEvent(device.System.KernelContext);
             _frameAvailableEvent = new KEvent(device.System.KernelContext);
 
 
-            Owner = process;
+            Owner = pid;
+
+            Active = true;
 
 
             BufferHistory        = new BufferInfo[BufferHistoryArraySize];
             BufferHistory        = new BufferInfo[BufferHistoryArraySize];
             EnableExternalEvent  = true;
             EnableExternalEvent  = true;
@@ -162,6 +166,16 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
             }
             }
         }
         }
 
 
+        public void PrepareForExit()
+        {
+            lock (Lock)
+            {
+                Active = false;
+
+                Monitor.PulseAll(Lock);
+            }
+        }
+
         // TODO: Find an accurate way to handle a regular condvar here as this will wake up unwanted threads in some edge cases.
         // TODO: Find an accurate way to handle a regular condvar here as this will wake up unwanted threads in some edge cases.
         public void SignalDequeueEvent()
         public void SignalDequeueEvent()
         {
         {
@@ -170,7 +184,11 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
 
 
         public void WaitDequeueEvent()
         public void WaitDequeueEvent()
         {
         {
-            Monitor.Wait(Lock);
+            Monitor.Exit(Lock);
+
+            KernelStatic.YieldUntilCompletion(WaitForLock);
+
+            Monitor.Enter(Lock);
         }
         }
 
 
         public void SignalIsAllocatingEvent()
         public void SignalIsAllocatingEvent()
@@ -180,7 +198,22 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
 
 
         public void WaitIsAllocatingEvent()
         public void WaitIsAllocatingEvent()
         {
         {
-            Monitor.Wait(Lock);
+            Monitor.Exit(Lock);
+
+            KernelStatic.YieldUntilCompletion(WaitForLock);
+
+            Monitor.Enter(Lock);
+        }
+
+        private void WaitForLock()
+        {
+            lock (Lock)
+            {
+                if (Active)
+                {
+                    Monitor.Wait(Lock);
+                }
+            }
         }
         }
 
 
         public void FreeBufferLocked(int slot)
         public void FreeBufferLocked(int slot)

+ 5 - 0
Ryujinx.HLE/HOS/Services/SurfaceFlinger/BufferQueueProducer.cs

@@ -816,6 +816,11 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
                     }
                     }
 
 
                     Core.WaitDequeueEvent();
                     Core.WaitDequeueEvent();
+
+                    if (!Core.Active)
+                    {
+                        break;
+                    }
                 }
                 }
             }
             }
 
 

+ 1 - 1
Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs

@@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
 {
 {
     abstract class IHOSBinderDriver : IpcService
     abstract class IHOSBinderDriver : IpcService
     {
     {
-        public IHOSBinderDriver() {}
+        public IHOSBinderDriver() { }
 
 
         [Command(0)]
         [Command(0)]
         // TransactParcel(s32, u32, u32, buffer<unknown, 5, 0>) -> buffer<unknown, 6, 0>
         // TransactParcel(s32, u32, u32, buffer<unknown, 5, 0>) -> buffer<unknown, 6, 0>

+ 15 - 11
Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs

@@ -1,10 +1,7 @@
 using Ryujinx.Common.Logging;
 using Ryujinx.Common.Logging;
 using Ryujinx.Graphics.GAL;
 using Ryujinx.Graphics.GAL;
 using Ryujinx.Graphics.Gpu;
 using Ryujinx.Graphics.Gpu;
-using Ryujinx.HLE.HOS.Kernel.Process;
-using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
 using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
-using Ryujinx.HLE.HOS.Services.Nv.Types;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Diagnostics;
@@ -40,7 +37,8 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
             public int                    ProducerBinderId;
             public int                    ProducerBinderId;
             public IGraphicBufferProducer Producer;
             public IGraphicBufferProducer Producer;
             public BufferItemConsumer     Consumer;
             public BufferItemConsumer     Consumer;
-            public KProcess               Owner;
+            public BufferQueueCore        Core;
+            public long                   Owner;
         }
         }
 
 
         private class TextureCallbackInformation
         private class TextureCallbackInformation
@@ -84,7 +82,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
             }
             }
         }
         }
 
 
-        public IGraphicBufferProducer OpenLayer(KProcess process, long layerId)
+        public IGraphicBufferProducer OpenLayer(long pid, long layerId)
         {
         {
             bool needCreate;
             bool needCreate;
 
 
@@ -95,13 +93,13 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
 
 
             if (needCreate)
             if (needCreate)
             {
             {
-                CreateLayerFromId(process, layerId);
+                CreateLayerFromId(pid, layerId);
             }
             }
 
 
             return GetProducerByLayerId(layerId);
             return GetProducerByLayerId(layerId);
         }
         }
 
 
-        public IGraphicBufferProducer CreateLayer(KProcess process, out long layerId)
+        public IGraphicBufferProducer CreateLayer(long pid, out long layerId)
         {
         {
             layerId = 1;
             layerId = 1;
 
 
@@ -116,25 +114,26 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
                 }
                 }
             }
             }
 
 
-            CreateLayerFromId(process, layerId);
+            CreateLayerFromId(pid, layerId);
 
 
             return GetProducerByLayerId(layerId);
             return GetProducerByLayerId(layerId);
         }
         }
 
 
-        private void CreateLayerFromId(KProcess process, long layerId)
+        private void CreateLayerFromId(long pid, long layerId)
         {
         {
             lock (Lock)
             lock (Lock)
             {
             {
                 Logger.Info?.Print(LogClass.SurfaceFlinger, $"Creating layer {layerId}");
                 Logger.Info?.Print(LogClass.SurfaceFlinger, $"Creating layer {layerId}");
 
 
-                BufferQueue.CreateBufferQueue(_device, process, out BufferQueueProducer producer, out BufferQueueConsumer consumer);
+                BufferQueueCore core = BufferQueue.CreateBufferQueue(_device, pid, out BufferQueueProducer producer, out BufferQueueConsumer consumer);
 
 
                 _layers.Add(layerId, new Layer
                 _layers.Add(layerId, new Layer
                 {
                 {
                     ProducerBinderId = HOSBinderDriverServer.RegisterBinderObject(producer),
                     ProducerBinderId = HOSBinderDriverServer.RegisterBinderObject(producer),
                     Producer         = producer,
                     Producer         = producer,
                     Consumer         = new BufferItemConsumer(_device, consumer, 0, -1, false, this),
                     Consumer         = new BufferItemConsumer(_device, consumer, 0, -1, false, this),
-                    Owner            = process
+                    Core             = core,
+                    Owner            = pid
                 });
                 });
 
 
                 LastId = layerId;
                 LastId = layerId;
@@ -345,6 +344,11 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
         public void Dispose()
         public void Dispose()
         {
         {
             _isRunning = false;
             _isRunning = false;
+
+            foreach (Layer layer in _layers.Values)
+            {
+                layer.Core.PrepareForExit();
+            }
         }
         }
 
 
         public void OnFrameAvailable(ref BufferItem item)
         public void OnFrameAvailable(ref BufferItem item)

+ 6 - 6
Ryujinx.HLE/HOS/Services/SurfaceFlinger/Types/GraphicBuffer.cs

@@ -42,23 +42,23 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
             Buffer = parcel.ReadUnmanagedType<NvGraphicBuffer>();
             Buffer = parcel.ReadUnmanagedType<NvGraphicBuffer>();
         }
         }
 
 
-        public void IncrementNvMapHandleRefCount(KProcess process)
+        public void IncrementNvMapHandleRefCount(long pid)
         {
         {
-            NvMapDeviceFile.IncrementMapRefCount(process, Buffer.NvMapId);
+            NvMapDeviceFile.IncrementMapRefCount(pid, Buffer.NvMapId);
 
 
             for (int i = 0; i < Buffer.Surfaces.Length; i++)
             for (int i = 0; i < Buffer.Surfaces.Length; i++)
             {
             {
-                NvMapDeviceFile.IncrementMapRefCount(process, Buffer.Surfaces[i].NvMapHandle);
+                NvMapDeviceFile.IncrementMapRefCount(pid, Buffer.Surfaces[i].NvMapHandle);
             }
             }
         }
         }
 
 
-        public void DecrementNvMapHandleRefCount(KProcess process)
+        public void DecrementNvMapHandleRefCount(long pid)
         {
         {
-            NvMapDeviceFile.DecrementMapRefCount(process, Buffer.NvMapId);
+            NvMapDeviceFile.DecrementMapRefCount(pid, Buffer.NvMapId);
 
 
             for (int i = 0; i < Buffer.Surfaces.Length; i++)
             for (int i = 0; i < Buffer.Surfaces.Length; i++)
             {
             {
-                NvMapDeviceFile.DecrementMapRefCount(process, Buffer.Surfaces[i].NvMapHandle);
+                NvMapDeviceFile.DecrementMapRefCount(pid, Buffer.Surfaces[i].NvMapHandle);
             }
             }
         }
         }
 
 

+ 3 - 1
Ryujinx.HLE/HOS/Services/Time/IStaticServiceForGlue.cs

@@ -15,10 +15,12 @@ namespace Ryujinx.HLE.HOS.Services.Time
         private IStaticServiceForPsc _inner;
         private IStaticServiceForPsc _inner;
         private TimePermissions      _permissions;
         private TimePermissions      _permissions;
 
 
-        public IStaticServiceForGlue(ServiceCtx context, TimePermissions permissions) : base(new ServerBase("TimeServer"))
+        public IStaticServiceForGlue(ServiceCtx context, TimePermissions permissions) : base(new ServerBase(context.Device.System.KernelContext, "TimeServer"))
         {
         {
             _permissions = permissions;
             _permissions = permissions;
             _inner       = new IStaticServiceForPsc(context, permissions);
             _inner       = new IStaticServiceForPsc(context, permissions);
+            _inner.TrySetServer(Server);
+            _inner.SetParent(this);
         }
         }
 
 
         [Command(0)]
         [Command(0)]

+ 6 - 6
Ryujinx.HLE/HOS/Services/Time/ITimeServiceManager.cs

@@ -149,7 +149,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
         public ResultCode Unknown50(ServiceCtx context)
         public ResultCode Unknown50(ServiceCtx context)
         {
         {
             // TODO: figure out the usage of this event
             // TODO: figure out the usage of this event
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(51)]
         [Command(51)]
@@ -157,7 +157,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
         public ResultCode Unknown51(ServiceCtx context)
         public ResultCode Unknown51(ServiceCtx context)
         {
         {
             // TODO: figure out the usage of this event
             // TODO: figure out the usage of this event
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(52)]
         [Command(52)]
@@ -165,7 +165,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
         public ResultCode Unknown52(ServiceCtx context)
         public ResultCode Unknown52(ServiceCtx context)
         {
         {
             // TODO: figure out the usage of this event
             // TODO: figure out the usage of this event
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(60)]
         [Command(60)]
@@ -201,7 +201,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
         public ResultCode GetAlarmRegistrationEvent(ServiceCtx context)
         public ResultCode GetAlarmRegistrationEvent(ServiceCtx context)
         {
         {
             // TODO
             // TODO
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(201)]
         [Command(201)]
@@ -209,7 +209,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
         public ResultCode UpdateSteadyAlarms(ServiceCtx context)
         public ResultCode UpdateSteadyAlarms(ServiceCtx context)
         {
         {
             // TODO
             // TODO
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
 
 
         [Command(202)]
         [Command(202)]
@@ -217,7 +217,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
         public ResultCode TryGetNextSteadyClockAlarmSnapshot(ServiceCtx context)
         public ResultCode TryGetNextSteadyClockAlarmSnapshot(ServiceCtx context)
         {
         {
             // TODO
             // TODO
-            throw new ServiceNotImplementedException(context);
+            throw new ServiceNotImplementedException(this, context);
         }
         }
     }
     }
 }
 }

+ 1 - 2
Ryujinx.HLE/HOS/Services/Vi/IApplicationRootService.cs

@@ -5,8 +5,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
     [Service("vi:u")]
     [Service("vi:u")]
     class IApplicationRootService : IpcService
     class IApplicationRootService : IpcService
     {
     {
-        // vi:u/m/s aren't on 3 separate threads but we can't put them together with the current ServerBase
-        public IApplicationRootService(ServiceCtx context) : base(new ServerBase("ViServerU")) { }
+        public IApplicationRootService(ServiceCtx context) : base(new ServerBase(context.Device.System.KernelContext, "ViServerU")) { }
 
 
         [Command(0)]
         [Command(0)]
         // GetDisplayService(u32) -> object<nn::visrv::sf::IApplicationDisplayService>
         // GetDisplayService(u32) -> object<nn::visrv::sf::IApplicationDisplayService>

+ 1 - 1
Ryujinx.HLE/HOS/Services/Vi/IManagerRootService.cs

@@ -6,7 +6,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
     class IManagerRootService : IpcService
     class IManagerRootService : IpcService
     {
     {
         // vi:u/m/s aren't on 3 separate threads but we can't put them together with the current ServerBase
         // vi:u/m/s aren't on 3 separate threads but we can't put them together with the current ServerBase
-        public IManagerRootService(ServiceCtx context) : base(new ServerBase("ViServerM")) { }
+        public IManagerRootService(ServiceCtx context) : base(new ServerBase(context.Device.System.KernelContext, "ViServerM")) { }
 
 
         [Command(2)]
         [Command(2)]
         // GetDisplayService(u32) -> object<nn::visrv::sf::IApplicationDisplayService>
         // GetDisplayService(u32) -> object<nn::visrv::sf::IApplicationDisplayService>

+ 1 - 1
Ryujinx.HLE/HOS/Services/Vi/ISystemRootService.cs

@@ -6,7 +6,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
     class ISystemRootService : IpcService
     class ISystemRootService : IpcService
     {
     {
         // vi:u/m/s aren't on 3 separate threads but we can't put them together with the current ServerBase
         // vi:u/m/s aren't on 3 separate threads but we can't put them together with the current ServerBase
-        public ISystemRootService(ServiceCtx context) : base(new ServerBase("ViServerS")) { }
+        public ISystemRootService(ServiceCtx context) : base(new ServerBase(context.Device.System.KernelContext, "ViServerS")) { }
 
 
         [Command(1)]
         [Command(1)]
         // GetDisplayService(u32) -> object<nn::visrv::sf::IApplicationDisplayService>
         // GetDisplayService(u32) -> object<nn::visrv::sf::IApplicationDisplayService>

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است