From b94dc01d4357c608d60383e85f709312294fd833 Mon Sep 17 00:00:00 2001 From: Mary Date: Wed, 5 May 2021 23:44:26 +0200 Subject: 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. --- Ryujinx.HLE/HOS/Services/ServerBase.cs | 27 +++++++++++++++++++-------- Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs | 24 +++++++++++++++++------- 2 files changed, 36 insertions(+), 15 deletions(-) (limited to 'Ryujinx.HLE/HOS/Services') 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 _sessionHandles = new List(); private readonly List _portHandles = new List(); private readonly Dictionary _sessions = new Dictionary(); - private readonly Dictionary _ports = new Dictionary(); + private readonly Dictionary> _ports = new Dictionary>(); public ManualResetEvent InitDone { get; } - public IpcService SmObject { get; set; } + public Func 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 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,15 +15,20 @@ namespace Ryujinx.HLE.HOS.Services.Sm { class IUserInterface : IpcService { - private Dictionary _services; + private static Dictionary _services; - private readonly ConcurrentDictionary _registeredServices; + private static readonly ConcurrentDictionary _registeredServices; private readonly ServerBase _commonServer; private bool _isInitialized; public IUserInterface(KernelContext context) + { + _commonServer = new ServerBase(context, "CommonServer"); + } + + static IUserInterface() { _registeredServices = new ConcurrentDictionary(); @@ -31,10 +36,6 @@ namespace Ryujinx.HLE.HOS.Services.Sm .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 + 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; } -- cgit v1.2.3