Avoid crash when passing unallocated syncpoint IDs to EventWait

This commit is contained in:
Billy Laws 2021-10-22 19:00:05 +01:00 committed by PixelyIon
parent fbfad21f03
commit 6eeaa343f8
3 changed files with 19 additions and 0 deletions

View File

@ -40,6 +40,10 @@ namespace skyline::service::nvdrv::core {
return ReserveSyncpoint(FindFreeSyncpoint(), clientManaged); return ReserveSyncpoint(FindFreeSyncpoint(), clientManaged);
} }
bool SyncpointManager::IsSyncpointAllocated(u32 id) {
return (id <= soc::host1x::SyncpointCount) && syncpoints[id].reserved;
}
bool SyncpointManager::HasSyncpointExpired(u32 id, u32 threshold) { bool SyncpointManager::HasSyncpointExpired(u32 id, u32 threshold) {
const SyncpointInfo &syncpoint{syncpoints.at(id)}; const SyncpointInfo &syncpoint{syncpoints.at(id)};

View File

@ -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 bool reserved; //!< If the syncpoint is reserved or not, not to be confused with a reserved value
}; };
const DeviceState &state; const DeviceState &state;
std::array<SyncpointInfo, soc::host1x::SyncpointCount> syncpoints{}; std::array<SyncpointInfo, soc::host1x::SyncpointCount> syncpoints{};
std::mutex reservationLock; std::mutex reservationLock;
@ -40,6 +41,11 @@ namespace skyline::service::nvdrv::core {
public: public:
SyncpointManager(const DeviceState &state); 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 * @brief Finds a free syncpoint and reserves it
* @return The ID of the reserved syncpoint * @return The ID of the reserved syncpoint

View File

@ -76,6 +76,15 @@ namespace skyline::service::nvdrv::device::nvhost {
if (fence.id >= soc::host1x::SyncpointCount) if (fence.id >= soc::host1x::SyncpointCount)
return PosixResult::InvalidArgument; 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 // Check if the syncpoint has already expired using the last known values
if (core.syncpointManager.IsFenceSignalled(fence)) { if (core.syncpointManager.IsFenceSignalled(fence)) {
value.val = core.syncpointManager.ReadSyncpointMinValue(fence.id); value.val = core.syncpointManager.ReadSyncpointMinValue(fence.id);