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.
This commit is contained in:
Mary 2021-05-05 23:44:26 +02:00 committed by GitHub
parent eb056218a1
commit b94dc01d43
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 85 additions and 15 deletions

View file

@ -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;
}
}