diff --git a/nx/include/switch.h b/nx/include/switch.h index 586c9387..07ab1720 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -63,6 +63,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/runtime/env.h" diff --git a/nx/include/switch/kernel/svc.h b/nx/include/switch/kernel/svc.h index 54b96120..2df231f7 100644 --- a/nx/include/switch/kernel/svc.h +++ b/nx/include/switch/kernel/svc.h @@ -213,7 +213,7 @@ Result svcSleepThread(u64 nano); ///@} -///@name Synchronization +///@name Events ///@{ /** @@ -230,6 +230,14 @@ Result svcSignalEvent(Handle handle); */ Result svcClearEvent(Handle handle); +/** + * @brief Creates a new event. + * @return Result code. + * @note Syscall number 0x45. + * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. + */ +Result svcCreateEvent(Handle* rhandle_out, Handle* whandle_out); + ///@} ///@name Inter-process memory sharing 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..e7d4453e --- /dev/null +++ b/nx/include/switch/nvidia/gpu/error_notifier.h @@ -0,0 +1,9 @@ +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 13f6f60b..a549e74f 100644 --- a/nx/include/switch/nvidia/gpu/gpu.h +++ b/nx/include/switch/nvidia/gpu/gpu.h @@ -4,6 +4,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..558fdcd5 --- /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); }