From 99509a5412d9d518a63fb33c16d718220af01ddb Mon Sep 17 00:00:00 2001 From: JPikachu Date: Thu, 24 Jul 2025 22:55:43 +0100 Subject: [PATCH 1/2] [nvdrv] Implement SetErrorNotifier Implements SetErrorNotifier() based on Switch kernel behavior. Only mem is used; other fields are ignored. Guest misuse of offset or size is logged as an error and rejected. Games like Super Mario Odyssey or Xenoblade may use this mechanism to detect timeouts. --- .../hle/service/nvdrv/devices/nvhost_gpu.cpp | 19 ++++++++++++++++--- .../hle/service/nvdrv/devices/nvhost_gpu.h | 1 + 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index d01642fe7c..80d2f0b989 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -161,8 +161,21 @@ NvResult nvhost_gpu::ZCullBind(IoctlZCullBind& params) { } NvResult nvhost_gpu::SetErrorNotifier(IoctlSetErrorNotifier& params) { - LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset, - params.size, params.mem); + if (params.mem == 0) { + LOG_DEBUG(Service_NVDRV, "called, SetErrorNotifier deinitialized"); + error_notifier_mem = 0; + return NvResult::Success; + } + + if (params.offset != 0 || params.size != 0) { + LOG_ERROR(Service_NVDRV, + "called, SetErrorNotifier received non-zero offset/size (ignored): offset=0x{:X}, size=0x{:X}", + params.offset, params.size); + return NvResult::BadParameter; + } + + LOG_DEBUG(Service_NVDRV, "called, SetErrorNotifier initialized, mem=0x{:X}", params.mem); + error_notifier_mem = params.mem; return NvResult::Success; } @@ -228,7 +241,7 @@ NvResult nvhost_gpu::AllocateObjectContext(IoctlAllocObjCtx& params) { return NvResult::NotInitialized; } - switch (static_cast(params.class_num)) { + switch (static_cast(params.class_num)) { case CtxClasses::Ctx2D: case CtxClasses::Ctx3D: case CtxClasses::CtxCompute: diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index a017cc50d0..5cb053766a 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -172,6 +172,7 @@ private: s32_le nvmap_fd{}; u64_le user_data{}; IoctlZCullBind zcull_params{}; + u32_le error_notifier_mem{}; std::vector ctxObj_params{}; u32_le channel_priority{}; u32_le channel_timeslice{}; From 08f1453f6fbd839e931df4dd3b7338106a062561 Mon Sep 17 00:00:00 2001 From: JPikachu Date: Fri, 25 Jul 2025 13:01:44 +0100 Subject: [PATCH 2/2] [nvdrv] Ignore but don't reject offset and size uses It seems after investigation and testing that these are in fact not errors and are expected behaviour. So logging has been changed from error to debug and no longer returns a bad perameter. --- src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 80d2f0b989..18eae70e4f 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -168,10 +168,9 @@ NvResult nvhost_gpu::SetErrorNotifier(IoctlSetErrorNotifier& params) { } if (params.offset != 0 || params.size != 0) { - LOG_ERROR(Service_NVDRV, - "called, SetErrorNotifier received non-zero offset/size (ignored): offset=0x{:X}, size=0x{:X}", - params.offset, params.size); - return NvResult::BadParameter; + LOG_DEBUG(Service_NVDRV, + "called, SetErrorNotifier called with non-zero offset/size (ignored): offset=0x{:X}, size=0x{:X}", + params.offset, params.size); } LOG_DEBUG(Service_NVDRV, "called, SetErrorNotifier initialized, mem=0x{:X}", params.mem);