Return valid event handles with QueryEvent

Also add an exception for unimplemented event ids.

This commit doesn't implement accurately the events, this only define
different events for different event ids.
This commit is contained in:
Thog 2019-10-29 01:56:50 +01:00
parent c94b2da01b
commit 16669d576d
No known key found for this signature in database
GPG key ID: 0CD291558FAFDBC6
5 changed files with 171 additions and 6 deletions

View file

@ -24,7 +24,6 @@ namespace Ryujinx.HLE.HOS.Services.Nv
[Service("nvdrv:t")]
class INvDrvServices : IpcService
{
// TODO: everything
private static Dictionary<string, Type> _fileDeviceRegistry =
new Dictionary<string, Type>()
{
@ -329,7 +328,14 @@ namespace Ryujinx.HLE.HOS.Services.Nv
if (errorCode == NvResult.Success)
{
errorCode = ConvertInternalErrorCode(fileDevice.QueryEvent(out int eventHandle, eventId));
NvInternalResult internalResult = fileDevice.QueryEvent(out int eventHandle, eventId);
if (internalResult == NvInternalResult.NotImplemented)
{
throw new NvQueryEventlNotImplementedException(context, fileDevice, eventId);
}
errorCode = ConvertInternalErrorCode(internalResult);
if (errorCode == NvResult.Success)
{

View file

@ -1,12 +1,21 @@
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel.Types;
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel.Types;
using System;
namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
{
internal class NvHostGpuFileDevice : NvHostChannelFileDevice
{
private KEvent _smExceptionBptIntReportEvent;
private KEvent _smExceptionBptPauseReportEvent;
private KEvent _errorNotifierEvent;
public NvHostGpuFileDevice(ServiceCtx context) : base(context)
{
_smExceptionBptIntReportEvent = new KEvent(context.Device.System);
_smExceptionBptPauseReportEvent = new KEvent(context.Device.System);
_errorNotifierEvent = new KEvent(context.Device.System);
}
public override NvInternalResult Ioctl2(NvIoctl command, Span<byte> arguments, Span<byte> inlineInBuffer)
@ -25,6 +34,41 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
return result;
}
public override NvInternalResult QueryEvent(out int eventHandle, uint eventId)
{
// TODO: accurately represent and implement those events.
KEvent targetEvent = null;
switch (eventId)
{
case 0x1:
targetEvent = _smExceptionBptIntReportEvent;
break;
case 0x2:
targetEvent = _smExceptionBptPauseReportEvent;
break;
case 0x3:
targetEvent = _errorNotifierEvent;
break;
}
if (targetEvent != null)
{
if (_owner.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != KernelResult.Success)
{
throw new InvalidOperationException("Out of handles!");
}
}
else
{
eventHandle = 0;
return NvInternalResult.InvalidInput;
}
return NvInternalResult.Success;
}
private NvInternalResult SubmitGpfifoEx(ref SubmitGpfifoArguments arguments, Span<long> inlineData)
{
return SubmitGpfifo(ref arguments, inlineData);

View file

@ -1,4 +1,6 @@
using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Kernel.Common;
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;
@ -16,6 +18,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl
private bool _isProductionMode;
private NvHostSyncpt _syncpt;
private NvHostEvent[] _events;
private KEvent _dummyEvent;
public NvHostCtrlFileDevice(ServiceCtx context) : base(context)
{
@ -28,8 +31,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl
_isProductionMode = true;
}
_syncpt = new NvHostSyncpt();
_events = new NvHostEvent[EventsCount];
_syncpt = new NvHostSyncpt();
_events = new NvHostEvent[EventsCount];
_dummyEvent = new KEvent(context.Device.System);
}
public override NvInternalResult Ioctl(NvIoctl command, Span<byte> arguments)
@ -82,6 +86,28 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrl
return result;
}
public override NvInternalResult QueryEvent(out int eventHandle, uint eventId)
{
// TODO: implement SyncPts <=> KEvent logic accurately. For now we return a dummy event.
KEvent targetEvent = _dummyEvent;
if (targetEvent != null)
{
if (_owner.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != KernelResult.Success)
{
throw new InvalidOperationException("Out of handles!");
}
}
else
{
eventHandle = 0;
return NvInternalResult.InvalidInput;
}
return NvInternalResult.Success;
}
private NvInternalResult SyncptRead(ref NvFence arguments)
{
return SyncptReadMinOrMax(ref arguments, max: false);

View file

@ -1,5 +1,7 @@
using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu.Types;
using System;
using System.Diagnostics;
@ -11,9 +13,13 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu
private static Stopwatch _pTimer = new Stopwatch();
private static double _ticksToNs = (1.0 / Stopwatch.Frequency) * 1_000_000_000;
private KEvent _errorEvent;
private KEvent _unknownEvent;
public NvHostCtrlGpuFileDevice(ServiceCtx context) : base(context)
{
_errorEvent = new KEvent(context.Device.System);
_unknownEvent = new KEvent(context.Device.System);
}
static NvHostCtrlGpuFileDevice()
@ -76,6 +82,38 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostCtrlGpu
return result;
}
public override NvInternalResult QueryEvent(out int eventHandle, uint eventId)
{
// TODO: accurately represent and implement those events.
KEvent targetEvent = null;
switch (eventId)
{
case 0x1:
targetEvent = _errorEvent;
break;
case 0x2:
targetEvent = _unknownEvent;
break;
}
if (targetEvent != null)
{
if (_owner.HandleTable.GenerateHandle(targetEvent.ReadableEvent, out eventHandle) != KernelResult.Success)
{
throw new InvalidOperationException("Out of handles!");
}
}
else
{
eventHandle = 0;
return NvInternalResult.InvalidInput;
}
return NvInternalResult.Success;
}
public override void Close()
{

View file

@ -0,0 +1,51 @@
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices;
using System;
using System.Text;
namespace Ryujinx.HLE.HOS.Services.Nv.Types
{
class NvQueryEventlNotImplementedException : Exception
{
public ServiceCtx Context { get; }
public NvFileDevice FileDevice { get; }
public uint EventId { get; }
public NvQueryEventlNotImplementedException(ServiceCtx context, NvFileDevice fileDevice, uint eventId)
: this(context, fileDevice, eventId, "The ioctl is not implemented.")
{ }
public NvQueryEventlNotImplementedException(ServiceCtx context, NvFileDevice fileDevice, uint eventId, string message)
: base(message)
{
Context = context;
FileDevice = fileDevice;
EventId = eventId;
}
public override string Message
{
get
{
return base.Message +
Environment.NewLine +
Environment.NewLine +
BuildMessage();
}
}
private string BuildMessage()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine($"Device File: {FileDevice.GetType().Name}");
sb.AppendLine();
sb.AppendLine($"Event ID: (0x{EventId:x8})");
sb.AppendLine("Guest Stack Trace:");
sb.AppendLine(Context.Thread.GetGuestStackTrace());
return sb.ToString();
}
}
}