From ab95d28e300643a17fa3ce74975dee68b8251ec5 Mon Sep 17 00:00:00 2001 From: plutoo Date: Sun, 11 Mar 2018 01:31:46 +0100 Subject: [PATCH] Completing error notifier --- nx/include/switch.h | 1 + nx/include/switch/nvidia/gpu/error_notifier.h | 1 + nx/include/switch/nvidia/ioctl.h | 8 ++++++ nx/include/switch/services/nv.h | 12 +++++++++ nx/source/nvidia/gpu/error_notifier.c | 25 ++++++++++++++++--- nx/source/nvidia/ioctl/nvchannel.c | 4 +++ 6 files changed, 47 insertions(+), 4 deletions(-) diff --git a/nx/include/switch.h b/nx/include/switch.h index 07ab1720..a48c5e1b 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -22,6 +22,7 @@ extern "C" { #include "switch/kernel/tmem.h" #include "switch/kernel/shmem.h" #include "switch/kernel/mutex.h" +#include "switch/kernel/event.h" #include "switch/kernel/rwlock.h" #include "switch/kernel/condvar.h" #include "switch/kernel/thread.h" diff --git a/nx/include/switch/nvidia/gpu/error_notifier.h b/nx/include/switch/nvidia/gpu/error_notifier.h index e7d4453e..e8e2f299 100644 --- a/nx/include/switch/nvidia/gpu/error_notifier.h +++ b/nx/include/switch/nvidia/gpu/error_notifier.h @@ -2,6 +2,7 @@ typedef struct NvGpu NvGpu; typedef struct { NvGpu* parent; + Event event; bool has_init; } NvErrorNotifier; diff --git a/nx/include/switch/nvidia/ioctl.h b/nx/include/switch/nvidia/ioctl.h index 403b6207..f6c31f43 100644 --- a/nx/include/switch/nvidia/ioctl.h +++ b/nx/include/switch/nvidia/ioctl.h @@ -140,6 +140,13 @@ typedef enum { NvErrorType_PbdmaPushbufferCrcMismatch=80 } NvErrorType; +typedef struct { + u64 tickstamp; + u32 error_type; + u16 unk16; + u16 status; // always -1 +} NvError; + 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); @@ -166,6 +173,7 @@ Result nvioctlChannel_SubmitGpfifo(u32 fd, nvioctl_gpfifo_entry *entries, u32 nu 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, u32 enable); +Result nvioctlChannel_GetErrorNotification(u32 fd, NvError* out); 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/include/switch/services/nv.h b/nx/include/switch/services/nv.h index c0c1c906..73aa9fc9 100644 --- a/nx/include/switch/services/nv.h +++ b/nx/include/switch/services/nv.h @@ -10,6 +10,18 @@ Result nvInitialize(void); void nvExit(void); +typedef enum { + NvEventId_Gpu_SmException_BptIntReport=1, + NvEventId_Gpu_SmException_BptPauseReport=2, + NvEventId_Gpu_ErrorNotifier=3, + + NvEventId_CtrlGpu_ErrorEventHandle=1, + NvEventId_CtrlGpu_Unknown=2, +} NvEventId; + +#define NV_EVENT_ID_CTRL__SYNCPT(slot, syncpt) \ + ((1u<<28) | ((syncpt) << 16) | (slot)) + Result nvOpen(u32 *fd, const char *devicepath); Result nvIoctl(u32 fd, u32 request, void* argp); Result nvClose(u32 fd); diff --git a/nx/source/nvidia/gpu/error_notifier.c b/nx/source/nvidia/gpu/error_notifier.c index 558fdcd5..bcb72d16 100644 --- a/nx/source/nvidia/gpu/error_notifier.c +++ b/nx/source/nvidia/gpu/error_notifier.c @@ -1,9 +1,16 @@ #include -Result nverrCreate(NvErrorNotifier* t, NvGpu* parent) { +Result nverrCreate(NvErrorNotifier* t, NvGpu* parent) +{ Result rc; + Handle handle; - rc = nvioctlChannel_SetErrorNotifier(parent->gpu_channel.fd, 1); + rc = nvQueryEvent(parent->gpu_channel.fd, NvEventId_Gpu_ErrorNotifier, &handle); + + if (R_SUCCEEDED(rc)) { + eventLoadRemote(&t->event, handle); + rc = nvioctlChannel_SetErrorNotifier(parent->gpu_channel.fd, 1); + } if (R_SUCCEEDED(rc)) { t->parent = parent; @@ -13,9 +20,19 @@ Result nverrCreate(NvErrorNotifier* t, NvGpu* parent) { return rc; } -void nverrClose(NvErrorNotifier* t) { +void nverrClose(NvErrorNotifier* t) +{ if (!t->has_init) return; - nvioctlChannel_SetErrorNotifier(t->parent->gpu_channel.fd, 0); + nvioctlChannel_SetErrorNotifier(t->parent->gpu_channel.fd, 0); + eventClose(&t->event); +} + +Result nverrWait(NvErrorNotifier* t, u64 timeout) { + return eventWait(&t->event, timeout); +} + +Result nverrGetError(NvErrorNotifier* t, NvError* out) { + return nvioctlChannel_GetErrorNotification(t->parent->gpu_channel.fd, out); } diff --git a/nx/source/nvidia/ioctl/nvchannel.c b/nx/source/nvidia/ioctl/nvchannel.c index 246140d7..554c08e0 100644 --- a/nx/source/nvidia/ioctl/nvchannel.c +++ b/nx/source/nvidia/ioctl/nvchannel.c @@ -100,6 +100,10 @@ Result nvioctlChannel_SetErrorNotifier(u32 fd, u32 enable) { return nvIoctl(fd, _NV_IOWR(0x48, 0x0C, data), &data); } +Result nvioctlChannel_GetErrorNotification(u32 fd, NvError* out) { + return nvIoctl(fd, _NV_IOWR(0x48, 0x17, *out), out); +} + Result nvioctlChannel_SetPriority(u32 fd, u32 priority) { struct { __nv_in u32 priority; // 0x32 is low, 0x64 is medium and 0x96 is high