From 6eeaa343f81f950f59a5310b0853e2da956237e0 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Fri, 22 Oct 2021 19:00:05 +0100 Subject: [PATCH] Avoid crash when passing unallocated syncpoint IDs to EventWait --- .../skyline/services/nvdrv/core/syncpoint_manager.cpp | 4 ++++ .../cpp/skyline/services/nvdrv/core/syncpoint_manager.h | 6 ++++++ .../cpp/skyline/services/nvdrv/devices/nvhost/ctrl.cpp | 9 +++++++++ 3 files changed, 19 insertions(+) diff --git a/app/src/main/cpp/skyline/services/nvdrv/core/syncpoint_manager.cpp b/app/src/main/cpp/skyline/services/nvdrv/core/syncpoint_manager.cpp index 00582dd4..7e3727fe 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/core/syncpoint_manager.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/core/syncpoint_manager.cpp @@ -40,6 +40,10 @@ namespace skyline::service::nvdrv::core { return ReserveSyncpoint(FindFreeSyncpoint(), clientManaged); } + bool SyncpointManager::IsSyncpointAllocated(u32 id) { + return (id <= soc::host1x::SyncpointCount) && syncpoints[id].reserved; + } + bool SyncpointManager::HasSyncpointExpired(u32 id, u32 threshold) { const SyncpointInfo &syncpoint{syncpoints.at(id)}; diff --git a/app/src/main/cpp/skyline/services/nvdrv/core/syncpoint_manager.h b/app/src/main/cpp/skyline/services/nvdrv/core/syncpoint_manager.h index f40f8636..7cb8c1a1 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/core/syncpoint_manager.h +++ b/app/src/main/cpp/skyline/services/nvdrv/core/syncpoint_manager.h @@ -23,6 +23,7 @@ namespace skyline::service::nvdrv::core { bool reserved; //!< If the syncpoint is reserved or not, not to be confused with a reserved value }; + const DeviceState &state; std::array syncpoints{}; std::mutex reservationLock; @@ -40,6 +41,11 @@ namespace skyline::service::nvdrv::core { public: SyncpointManager(const DeviceState &state); + /** + * @brief Checks if the given syncpoint is both allocated and below the number of HW syncpoints + */ + bool IsSyncpointAllocated(u32 id); + /** * @brief Finds a free syncpoint and reserves it * @return The ID of the reserved syncpoint diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/ctrl.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/ctrl.cpp index d672c786..25ad1076 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/ctrl.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost/ctrl.cpp @@ -76,6 +76,15 @@ namespace skyline::service::nvdrv::device::nvhost { if (fence.id >= soc::host1x::SyncpointCount) return PosixResult::InvalidArgument; + // No need to wait since syncpoints start at 0 + if (fence.threshold == 0) { + // oss-nvjpg waits on syncpoint 0 during initialisation without reserving it, this is technically valid with a zero threshold but could also be a sign of a bug on our side in other cases, hence the warn + if (!core.syncpointManager.IsSyncpointAllocated(fence.id)) + state.logger->Warn("Tried to wait on an unreserved syncpoint with no threshold"); + + return PosixResult::Success; + } + // Check if the syncpoint has already expired using the last known values if (core.syncpointManager.IsFenceSignalled(fence)) { value.val = core.syncpointManager.ReadSyncpointMinValue(fence.id);