diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2020-12-01 20:23:43 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-12-02 00:23:43 +0100 |
| commit | cf6cd714884c41e9550757e364c2f4f5b04fc7f3 (patch) | |
| tree | bea748b4d1a350e5b8075d63ec9d39d49693829d /Ryujinx.HLE/HOS/Services/Nv | |
| parent | 461c24092ae6e148d896c18aa3e86220c89981f8 (diff) | |
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>
Diffstat (limited to 'Ryujinx.HLE/HOS/Services/Nv')
8 files changed, 66 insertions, 60 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs b/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs index 0812683b..9f1ace36 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs @@ -4,7 +4,6 @@ using Ryujinx.Cpu; using Ryujinx.HLE.Exceptions; using Ryujinx.HLE.HOS.Ipc; 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.NvHostAsGpu; 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.NvMap; using Ryujinx.HLE.HOS.Services.Nv.Types; +using Ryujinx.Memory; using System; using System.Collections.Generic; using System.Reflection; @@ -27,47 +27,45 @@ namespace Ryujinx.HLE.HOS.Services.Nv private static Dictionary<string, Type> _deviceFileRegistry = 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 KProcess _owner; + private IVirtualMemoryManager _clientMemory; + private long _owner; 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) { - 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; @@ -150,7 +148,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv return NvResult.NotImplemented; } - if (deviceFile.Owner.Pid != _owner.Pid) + if (deviceFile.Owner != _owner) { return NvResult.AccessDenied; } @@ -160,7 +158,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv private NvResult EnsureInitialized() { - if (_owner == null) + if (_owner == 0) { Logger.Warning?.Print(LogClass.ServiceNv, "INvDrvServices is not initialized!"); @@ -229,8 +227,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv if (errorCode == NvResult.Success) { 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); @@ -322,7 +321,11 @@ namespace Ryujinx.HLE.HOS.Services.Nv // TODO: When transfer memory will be implemented, this could be removed. _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); @@ -425,7 +428,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv // ForceSetClientPid(u64) -> u32 error_code public ResultCode ForceSetClientPid(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(8)] @@ -452,7 +455,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv // InitializeDevtools(u32, handle<copy>) -> u32 error_code; public ResultCode InitializeDevtools(ServiceCtx context) { - throw new ServiceNotImplementedException(context); + throw new ServiceNotImplementedException(this, context); } [Command(11)] // 3.0.0+ diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvDeviceFile.cs index af4734ea..34ff4ccb 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvDeviceFile.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvDeviceFile.cs @@ -1,6 +1,5 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Kernel.Memory; -using Ryujinx.HLE.HOS.Kernel.Process; using System; using System.Diagnostics; using System.Reflection; @@ -12,14 +11,14 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices abstract class NvDeviceFile { public readonly ServiceCtx Context; - public readonly KProcess Owner; + public readonly long Owner; public string Path; - public NvDeviceFile(ServiceCtx context) + public NvDeviceFile(ServiceCtx context, long owner) { Context = context; - Owner = context.Process; + Owner = owner; } public virtual NvInternalResult QueryEvent(out int eventHandle, uint eventId) diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs index 0000f495..6c49fd5c 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs +++ b/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.Services.Nv.NvDrvServices.NvHostAsGpu.Types; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap; +using Ryujinx.Memory; using System; 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>(); - 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) { diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs index 863b01d1..d675ffc7 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostChannelDeviceFile.cs +++ b/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.NvMap; using Ryujinx.HLE.HOS.Services.Nv.Types; +using Ryujinx.Memory; using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -19,9 +20,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel private uint _submitTimeout; private uint _timeslice; - private Switch _device; + private readonly Switch _device; - private Cpu.MemoryManager _memory; + private readonly IVirtualMemoryManager _memory; public enum ResourcePolicy { @@ -37,10 +38,10 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel private NvFence _channelSyncpoint; - public NvHostChannelDeviceFile(ServiceCtx context) : base(context) + public NvHostChannelDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, long owner) : base(context, owner) { _device = context.Device; - _memory = context.Memory; + _memory = memory; _timeout = 3000; _submitTimeout = 0; _timeslice = 0; diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostGpuDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostGpuDeviceFile.cs index 52389140..f27c065e 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostGpuDeviceFile.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostChannel/NvHostGpuDeviceFile.cs @@ -1,6 +1,7 @@ using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel.Types; +using Ryujinx.Memory; using System; 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 _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); _smExceptionBptPauseReportEvent = new KEvent(context.Device.System.KernelContext); @@ -55,7 +56,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel 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!"); } diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs index a5384596..f0e5634e 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrl/NvHostCtrlDeviceFile.cs +++ b/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.Types; using Ryujinx.HLE.HOS.Services.Settings; - +using Ryujinx.Memory; using System; using System.Text; using System.Threading; @@ -20,7 +20,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl private Switch _device; 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)) { @@ -126,7 +126,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl 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!"); } diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrlGpu/NvHostCtrlGpuDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrlGpu/NvHostCtrlGpuDeviceFile.cs index e0acf0df..840d95b9 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrlGpu/NvHostCtrlGpuDeviceFile.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostCtrlGpu/NvHostCtrlGpuDeviceFile.cs @@ -2,6 +2,7 @@ using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu.Types; +using Ryujinx.Memory; using System; using System.Diagnostics; @@ -15,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu private KEvent _errorEvent; 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); _unknownEvent = new KEvent(context.Device.System.KernelContext); @@ -98,7 +99,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu 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!"); } diff --git a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvMap/NvMapDeviceFile.cs b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvMap/NvMapDeviceFile.cs index 3cc47c42..a549c81c 100644 --- a/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvMap/NvMapDeviceFile.cs +++ b/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvMap/NvMapDeviceFile.cs @@ -1,7 +1,7 @@ using Ryujinx.Common; using Ryujinx.Common.Logging; using Ryujinx.Graphics.Gpu.Memory; -using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.Memory; using System; using System.Collections.Concurrent; @@ -11,9 +11,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap { 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()); @@ -244,9 +244,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap 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; } @@ -254,14 +254,14 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap 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) { @@ -270,7 +270,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap if (map.DecrementRefCount() <= 0) { - DeleteMapWithHandle(process, handle); + DeleteMapWithHandle(pid, 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); } |
