diff --git a/nx/include/switch.h b/nx/include/switch.h index c4be1010..554b5696 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -79,6 +79,7 @@ extern "C" { #include "switch/nvidia/gpu/gpfifo.h" #include "switch/nvidia/gpu/zcull_ctx.h" #include "switch/nvidia/gpu/3d_ctx.h" +#include "switch/nvidia/gpu/error_notifier.h" #include "switch/nvidia/gpu/gpu.h" #include "switch/audio/driver.h" diff --git a/nx/include/switch/nvidia/gpu/error_notifier.h b/nx/include/switch/nvidia/gpu/error_notifier.h new file mode 100644 index 00000000..6333349e --- /dev/null +++ b/nx/include/switch/nvidia/gpu/error_notifier.h @@ -0,0 +1,11 @@ +#pragma once + +typedef struct NvGpu NvGpu; + +typedef struct { + NvGpu* parent; + bool has_init; +} NvErrorNotifier; + +Result nverrCreate(NvErrorNotifier* t, NvGpu* parent); +void nverrClose(NvErrorNotifier* t); diff --git a/nx/include/switch/nvidia/gpu/gpu.h b/nx/include/switch/nvidia/gpu/gpu.h index 08b399df..0743fae1 100644 --- a/nx/include/switch/nvidia/gpu/gpu.h +++ b/nx/include/switch/nvidia/gpu/gpu.h @@ -6,6 +6,7 @@ typedef struct NvGpu { NvGpfifo gpfifo; NvZcullContext zcull_ctx; Nv3dContext _3d_ctx; + NvErrorNotifier error_notifier; } NvGpu; Result nvgpuCreate(NvGpu* g); diff --git a/nx/include/switch/nvidia/ioctl.h b/nx/include/switch/nvidia/ioctl.h index cf521107..403b6207 100644 --- a/nx/include/switch/nvidia/ioctl.h +++ b/nx/include/switch/nvidia/ioctl.h @@ -129,6 +129,17 @@ typedef enum { NvZcullConfig_PartOfRegularBuffer = 3 } NvZcullConfig; +typedef enum { + NvErrorType_FifoErrorIdleTimeout=8, + NvErrorType_GrErrorSwNotify=13, + NvErrorType_GrSemaphoreTimeout=24, + NvErrorType_GrIllegalNotify=25, + NvErrorType_FifoErrorMmuErrFlt=31, + NvErrorType_PbdmaError=32, + NvErrorType_ResetChannelVerifError=43, + NvErrorType_PbdmaPushbufferCrcMismatch=80 +} NvErrorType; + Result nvioctlNvhostCtrl_EventSignal(u32 fd, u32 event_id); Result nvioctlNvhostCtrl_EventWait(u32 fd, u32 syncpt_id, u32 threshold, s32 timeout, u32 event_id, u32 *out); Result nvioctlNvhostCtrl_EventRegister(u32 fd, u32 event_id); @@ -154,7 +165,7 @@ Result nvioctlChannel_SetNvmapFd(u32 fd, u32 nvmap_fd); Result nvioctlChannel_SubmitGpfifo(u32 fd, nvioctl_gpfifo_entry *entries, u32 num_entries, u32 flags, nvioctl_fence *fence_out); Result nvioctlChannel_AllocObjCtx(u32 fd, u32 class_num, u32 flags, u64* id_out); Result nvioctlChannel_ZCullBind(u32 fd, u64 gpu_va, u32 mode); -Result nvioctlChannel_SetErrorNotifier(u32 fd, u64 offset, u64 size, u32 nvmap_handle); +Result nvioctlChannel_SetErrorNotifier(u32 fd, u32 enable); Result nvioctlChannel_SetPriority(u32 fd, u32 priority); Result nvioctlChannel_AllocGpfifoEx2(u32 fd, u32 num_entries, u32 flags, u32 unk0, u32 unk1, u32 unk2, u32 unk3, nvioctl_fence *fence_out); Result nvioctlChannel_SetUserData(u32 fd, void* addr); diff --git a/nx/source/nvidia/gpu/error_notifier.c b/nx/source/nvidia/gpu/error_notifier.c new file mode 100644 index 00000000..26e18116 --- /dev/null +++ b/nx/source/nvidia/gpu/error_notifier.c @@ -0,0 +1,21 @@ +#include + +Result nverrCreate(NvErrorNotifier* t, NvGpu* parent) { + Result rc; + + rc = nvioctlChannel_SetErrorNotifier(parent->gpu_channel.fd, 1); + + if (R_SUCCEEDED(rc)) { + t->parent = parent; + t->has_init = true; + } + + return rc; +} + +void nverrClose(NvErrorNotifier* t) { + if (!t->has_init) + return; + + nvioctlChannel_SetErrorNotifier(t->parent->gpu_channel.fd, 0); +} diff --git a/nx/source/nvidia/gpu/gpu.c b/nx/source/nvidia/gpu/gpu.c index fca00d91..5167b080 100644 --- a/nx/source/nvidia/gpu/gpu.c +++ b/nx/source/nvidia/gpu/gpu.c @@ -30,6 +30,9 @@ Result nvgpuCreate(NvGpu* g) if (R_SUCCEEDED(rc)) rc = nv3dCreate(&g->_3d_ctx, g); + if (R_SUCCEEDED(rc)) + rc = nverrCreate(&g->error_notifier, g); + if (R_SUCCEEDED(rc)) rc = nvchannelSetPriority(&g->gpu_channel, NvChannelPriority_Medium); @@ -47,6 +50,7 @@ void nvgpuClose(NvGpu* g) nvbufExit(); nvinfoExit(); + nverrClose(&g->error_notifier); nvzcullClose(&g->zcull_ctx); nv3dClose(&g->_3d_ctx); nvfifoClose(&g->gpfifo); diff --git a/nx/source/nvidia/ioctl/nvchannel.c b/nx/source/nvidia/ioctl/nvchannel.c index 9dcfe56a..246140d7 100644 --- a/nx/source/nvidia/ioctl/nvchannel.c +++ b/nx/source/nvidia/ioctl/nvchannel.c @@ -84,18 +84,18 @@ Result nvioctlChannel_ZCullBind(u32 fd, u64 gpu_va, u32 mode) { return nvIoctl(fd, _NV_IOWR(0x48, 0x0B, data), &data); } -Result nvioctlChannel_SetErrorNotifier(u32 fd, u64 offset, u64 size, u32 nvmap_handle) { +Result nvioctlChannel_SetErrorNotifier(u32 fd, u32 enable) { struct { - __nv_in u64 offset; - __nv_in u64 size; - __nv_in u32 nvmap_handle; + __nv_in u64 offset; // not used + __nv_in u64 size; // not used + __nv_in u32 enable; u32 padding; } data; memset(&data, 0, sizeof(data)); - data.offset = offset; - data.size = size; - data.nvmap_handle = nvmap_handle; + data.offset = 0; + data.size = 0; + data.enable = enable; return nvIoctl(fd, _NV_IOWR(0x48, 0x0C, data), &data); }