diff options
| author | Mary <me@thog.eu> | 2021-05-05 23:44:26 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-05-05 23:44:26 +0200 |
| commit | b94dc01d4357c608d60383e85f709312294fd833 (patch) | |
| tree | 3b4fff544218ed538fd8160498eddb3eba794fc0 /Ryujinx.HLE/HOS/Services | |
| parent | eb056218a13fa145adcc9ecafd166b1b1f2caccb (diff) | |
SM instance & TIPC fixes (#2241)
This PR addresses the following issues:
- SM was previously instancied once and reused on all sessions. This
could cause inconsistency on the service initialization.
- TIPC replies were not matching what is generated on hardware.
Diffstat (limited to 'Ryujinx.HLE/HOS/Services')
| -rw-r--r-- | Ryujinx.HLE/HOS/Services/ServerBase.cs | 27 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs | 24 |
2 files changed, 36 insertions, 15 deletions
diff --git a/Ryujinx.HLE/HOS/Services/ServerBase.cs b/Ryujinx.HLE/HOS/Services/ServerBase.cs index f957a624..5b9834dc 100644 --- a/Ryujinx.HLE/HOS/Services/ServerBase.cs +++ b/Ryujinx.HLE/HOS/Services/ServerBase.cs @@ -35,10 +35,10 @@ namespace Ryujinx.HLE.HOS.Services 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>(); + private readonly Dictionary<int, Func<IpcService>> _ports = new Dictionary<int, Func<IpcService>>(); public ManualResetEvent InitDone { get; } - public IpcService SmObject { get; set; } + public Func<IpcService> SmObjectFactory { get; set; } public string Name { get; } public ServerBase(KernelContext context, string name) @@ -58,10 +58,10 @@ namespace Ryujinx.HLE.HOS.Services KernelStatic.StartInitialProcess(context, creationInfo, DefaultCapabilities, 44, ServerLoop); } - private void AddPort(int serverPortHandle, IpcService obj) + private void AddPort(int serverPortHandle, Func<IpcService> objectFactory) { _portHandles.Add(serverPortHandle); - _ports.Add(serverPortHandle, obj); + _ports.Add(serverPortHandle, objectFactory); } public void AddSessionObj(KServerSession serverSession, IpcService obj) @@ -80,11 +80,11 @@ namespace Ryujinx.HLE.HOS.Services { _selfProcess = KernelStatic.GetCurrentProcess(); - if (SmObject != null) + if (SmObjectFactory != null) { _context.Syscall.ManageNamedPort("sm:", 50, out int serverPortHandle); - AddPort(serverPortHandle, SmObject); + AddPort(serverPortHandle, SmObjectFactory); InitDone.Set(); } @@ -141,7 +141,9 @@ namespace Ryujinx.HLE.HOS.Services // We got a new connection, accept the session to allow servicing future requests. if (_context.Syscall.AcceptSession(handles[signaledIndex], out int serverSessionHandle) == KernelResult.Success) { - AddSessionObj(serverSessionHandle, _ports[handles[signaledIndex]]); + IpcService obj = _ports[handles[signaledIndex]].Invoke(); + + AddSessionObj(serverSessionHandle, obj); } } @@ -191,6 +193,7 @@ namespace Ryujinx.HLE.HOS.Services } bool shouldReply = true; + bool isTipcCommunication = false; using (MemoryStream raw = new MemoryStream(request.RawData)) { @@ -269,6 +272,8 @@ namespace Ryujinx.HLE.HOS.Services // If the type is past 0xF, we are using TIPC else if (request.Type > IpcMessageType.TipcCloseSession) { + isTipcCommunication = true; + // Response type is always the same as request on TIPC. response.Type = request.Type; @@ -290,13 +295,19 @@ namespace Ryujinx.HLE.HOS.Services response.RawData = resMs.ToArray(); } + + process.CpuMemory.Write(messagePtr, response.GetBytesTipc()); } else { throw new NotImplementedException(request.Type.ToString()); } - process.CpuMemory.Write(messagePtr, response.GetBytes((long)messagePtr, recvListAddr | ((ulong)PointerBufferSize << 48))); + if (!isTipcCommunication) + { + process.CpuMemory.Write(messagePtr, response.GetBytes((long)messagePtr, recvListAddr | ((ulong)PointerBufferSize << 48))); + } + return shouldReply; } } diff --git a/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs b/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs index d5dabb2d..9a0ccbc3 100644 --- a/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs +++ b/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs @@ -15,9 +15,9 @@ namespace Ryujinx.HLE.HOS.Services.Sm { class IUserInterface : IpcService { - private Dictionary<string, Type> _services; + private static Dictionary<string, Type> _services; - private readonly ConcurrentDictionary<string, KPort> _registeredServices; + private static readonly ConcurrentDictionary<string, KPort> _registeredServices; private readonly ServerBase _commonServer; @@ -25,16 +25,17 @@ namespace Ryujinx.HLE.HOS.Services.Sm public IUserInterface(KernelContext context) { + _commonServer = new ServerBase(context, "CommonServer"); + } + + static IUserInterface() + { _registeredServices = new ConcurrentDictionary<string, KPort>(); _services = Assembly.GetExecutingAssembly().GetTypes() .SelectMany(type => type.GetCustomAttributes(typeof(ServiceAttribute), true) .Select(service => (((ServiceAttribute)service).Name, type))) .ToDictionary(service => service.Name, service => service.type); - - TrySetServer(new ServerBase(context, "SmServer") { SmObject = this }); - - _commonServer = new ServerBase(context, "CommonServer"); } [CommandHipc(0)] @@ -47,9 +48,16 @@ namespace Ryujinx.HLE.HOS.Services.Sm return ResultCode.Success; } - [CommandHipc(1)] [CommandTipc(1)] // 12.0.0+ // GetService(ServiceName name) -> handle<move, session> + public ResultCode GetServiceTipc(ServiceCtx context) + { + context.Response.HandleDesc = IpcHandleDesc.MakeMove(0); + + return GetService(context); + } + + [CommandHipc(1)] public ResultCode GetService(ServiceCtx context) { if (!_isInitialized) @@ -142,6 +150,8 @@ namespace Ryujinx.HLE.HOS.Services.Sm { if (!_isInitialized) { + context.Response.HandleDesc = IpcHandleDesc.MakeMove(0); + return ResultCode.NotInitialized; } |
