diff options
Diffstat (limited to '')
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/nvdrv.cpp | 53 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/nvdrv.h | 9 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/nvdrv_interface.cpp | 6 |
4 files changed, 40 insertions, 32 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 9b393521a..55acd4f78 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | |||
| @@ -125,8 +125,10 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector | |||
| 125 | } | 125 | } |
| 126 | }(); | 126 | }(); |
| 127 | 127 | ||
| 128 | must_unmark_fail = true; | ||
| 129 | |||
| 128 | const auto check_failing = [&]() { | 130 | const auto check_failing = [&]() { |
| 129 | if (events_interface.fails[slot] > 1) { | 131 | if (events_interface.fails[slot] > 2) { |
| 130 | { | 132 | { |
| 131 | auto lk = system.StallProcesses(); | 133 | auto lk = system.StallProcesses(); |
| 132 | gpu.WaitFence(fence_id, target_value); | 134 | gpu.WaitFence(fence_id, target_value); |
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index 7c0f89c12..df4656240 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp | |||
| @@ -29,6 +29,29 @@ | |||
| 29 | 29 | ||
| 30 | namespace Service::Nvidia { | 30 | namespace Service::Nvidia { |
| 31 | 31 | ||
| 32 | EventInterface::EventInterface(Module& module_) : module{module_} { | ||
| 33 | events_mask = 0; | ||
| 34 | for (u32 i = 0; i < MaxNvEvents; i++) { | ||
| 35 | status[i] = EventState::Available; | ||
| 36 | events[i] = nullptr; | ||
| 37 | registered[i] = false; | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | EventInterface::~EventInterface() { | ||
| 42 | auto lk = Lock(); | ||
| 43 | for (u32 i = 0; i < MaxNvEvents; i++) { | ||
| 44 | if (registered[i]) { | ||
| 45 | module.service_context.CloseEvent(events[i]); | ||
| 46 | events[i] = nullptr; | ||
| 47 | registered[i] = false; | ||
| 48 | } | ||
| 49 | } | ||
| 50 | for (auto* event : basic_events) { | ||
| 51 | module.service_context.CloseEvent(event); | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 32 | std::unique_lock<std::mutex> EventInterface::Lock() { | 55 | std::unique_lock<std::mutex> EventInterface::Lock() { |
| 33 | return std::unique_lock<std::mutex>(events_mutex); | 56 | return std::unique_lock<std::mutex>(events_mutex); |
| 34 | } | 57 | } |
| @@ -45,27 +68,25 @@ void EventInterface::Create(u32 event_id) { | |||
| 45 | ASSERT(!events[event_id]); | 68 | ASSERT(!events[event_id]); |
| 46 | ASSERT(!registered[event_id]); | 69 | ASSERT(!registered[event_id]); |
| 47 | ASSERT(!IsBeingUsed(event_id)); | 70 | ASSERT(!IsBeingUsed(event_id)); |
| 48 | events[event_id] = backup[event_id]; | 71 | events[event_id] = |
| 72 | module.service_context.CreateEvent(fmt::format("NVDRV::NvEvent_{}", event_id)); | ||
| 49 | status[event_id] = EventState::Available; | 73 | status[event_id] = EventState::Available; |
| 50 | registered[event_id] = true; | 74 | registered[event_id] = true; |
| 51 | const u64 mask = 1ULL << event_id; | 75 | const u64 mask = 1ULL << event_id; |
| 52 | fails[event_id] = 0; | 76 | fails[event_id] = 0; |
| 53 | events_mask |= mask; | 77 | events_mask |= mask; |
| 54 | LOG_CRITICAL(Service_NVDRV, "Created Event {}", event_id); | ||
| 55 | } | 78 | } |
| 56 | 79 | ||
| 57 | void EventInterface::Free(u32 event_id) { | 80 | void EventInterface::Free(u32 event_id) { |
| 58 | ASSERT(events[event_id]); | 81 | ASSERT(events[event_id]); |
| 59 | ASSERT(registered[event_id]); | 82 | ASSERT(registered[event_id]); |
| 60 | ASSERT(!IsBeingUsed(event_id)); | 83 | ASSERT(!IsBeingUsed(event_id)); |
| 61 | 84 | module.service_context.CloseEvent(events[event_id]); | |
| 62 | backup[event_id]->GetWritableEvent().Clear(); | ||
| 63 | events[event_id] = nullptr; | 85 | events[event_id] = nullptr; |
| 64 | status[event_id] = EventState::Available; | 86 | status[event_id] = EventState::Available; |
| 65 | registered[event_id] = false; | 87 | registered[event_id] = false; |
| 66 | const u64 mask = ~(1ULL << event_id); | 88 | const u64 mask = ~(1ULL << event_id); |
| 67 | events_mask &= mask; | 89 | events_mask &= mask; |
| 68 | LOG_CRITICAL(Service_NVDRV, "Freed Event {}", event_id); | ||
| 69 | } | 90 | } |
| 70 | 91 | ||
| 71 | u32 EventInterface::FindFreeEvent(u32 syncpoint_id) { | 92 | u32 EventInterface::FindFreeEvent(u32 syncpoint_id) { |
| @@ -114,15 +135,7 @@ void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger | |||
| 114 | } | 135 | } |
| 115 | 136 | ||
| 116 | Module::Module(Core::System& system) | 137 | Module::Module(Core::System& system) |
| 117 | : syncpoint_manager{system.GPU()}, events_interface{*this}, service_context{system, "nvdrv"} { | 138 | : syncpoint_manager{system.GPU()}, service_context{system, "nvdrv"}, events_interface{*this} { |
| 118 | events_interface.events_mask = 0; | ||
| 119 | for (u32 i = 0; i < MaxNvEvents; i++) { | ||
| 120 | events_interface.status[i] = EventState::Available; | ||
| 121 | events_interface.events[i] = nullptr; | ||
| 122 | events_interface.registered[i] = false; | ||
| 123 | events_interface.backup[i] = | ||
| 124 | service_context.CreateEvent(fmt::format("NVDRV::NvEvent_{}", i)); | ||
| 125 | } | ||
| 126 | auto nvmap_dev = std::make_shared<Devices::nvmap>(system); | 139 | auto nvmap_dev = std::make_shared<Devices::nvmap>(system); |
| 127 | devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>(system, nvmap_dev); | 140 | devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>(system, nvmap_dev); |
| 128 | devices["/dev/nvhost-gpu"] = std::make_shared<Devices::nvhost_gpu>( | 141 | devices["/dev/nvhost-gpu"] = std::make_shared<Devices::nvhost_gpu>( |
| @@ -140,15 +153,7 @@ Module::Module(Core::System& system) | |||
| 140 | std::make_shared<Devices::nvhost_vic>(system, nvmap_dev, syncpoint_manager); | 153 | std::make_shared<Devices::nvhost_vic>(system, nvmap_dev, syncpoint_manager); |
| 141 | } | 154 | } |
| 142 | 155 | ||
| 143 | Module::~Module() { | 156 | Module::~Module() = default; |
| 144 | auto lock = events_interface.Lock(); | ||
| 145 | for (u32 i = 0; i < MaxNvEvents; i++) { | ||
| 146 | if (events_interface.registered[i]) { | ||
| 147 | events_interface.Free(i); | ||
| 148 | } | ||
| 149 | service_context.CloseEvent(events_interface.backup[i]); | ||
| 150 | } | ||
| 151 | } | ||
| 152 | 157 | ||
| 153 | NvResult Module::VerifyFD(DeviceFD fd) const { | 158 | NvResult Module::VerifyFD(DeviceFD fd) const { |
| 154 | if (fd < 0) { | 159 | if (fd < 0) { |
| @@ -255,7 +260,7 @@ void Module::SignalSyncpt(const u32 syncpoint_id, const u32 value) { | |||
| 255 | const u32 max = MaxNvEvents - std::countl_zero(events_interface.events_mask); | 260 | const u32 max = MaxNvEvents - std::countl_zero(events_interface.events_mask); |
| 256 | const u32 min = std::countr_zero(events_interface.events_mask); | 261 | const u32 min = std::countr_zero(events_interface.events_mask); |
| 257 | for (u32 i = min; i < max; i++) { | 262 | for (u32 i = min; i < max; i++) { |
| 258 | if (events_interface.registered[i] && events_interface.assigned_syncpt[i] == syncpoint_id && | 263 | if (events_interface.assigned_syncpt[i] == syncpoint_id && |
| 259 | events_interface.assigned_value[i] == value) { | 264 | events_interface.assigned_value[i] == value) { |
| 260 | events_interface.Signal(i); | 265 | events_interface.Signal(i); |
| 261 | } | 266 | } |
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index be8813c97..d24b57539 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h | |||
| @@ -41,14 +41,13 @@ class Module; | |||
| 41 | 41 | ||
| 42 | class EventInterface { | 42 | class EventInterface { |
| 43 | public: | 43 | public: |
| 44 | EventInterface(Module& module_) : module{module_} {} | 44 | EventInterface(Module& module_); |
| 45 | ~EventInterface(); | ||
| 45 | 46 | ||
| 46 | // Mask representing registered events | 47 | // Mask representing registered events |
| 47 | u64 events_mask{}; | 48 | u64 events_mask{}; |
| 48 | // Each kernel event associated to an NV event | 49 | // Each kernel event associated to an NV event |
| 49 | std::array<Kernel::KEvent*, MaxNvEvents> events{}; | 50 | std::array<Kernel::KEvent*, MaxNvEvents> events{}; |
| 50 | // Backup NV event | ||
| 51 | std::array<Kernel::KEvent*, MaxNvEvents> backup{}; | ||
| 52 | // The status of the current NVEvent | 51 | // The status of the current NVEvent |
| 53 | std::array<std::atomic<EventState>, MaxNvEvents> status{}; | 52 | std::array<std::atomic<EventState>, MaxNvEvents> status{}; |
| 54 | // Tells if an NVEvent is registered or not | 53 | // Tells if an NVEvent is registered or not |
| @@ -139,10 +138,10 @@ private: | |||
| 139 | /// Mapping of device node names to their implementation. | 138 | /// Mapping of device node names to their implementation. |
| 140 | std::unordered_map<std::string, std::shared_ptr<Devices::nvdevice>> devices; | 139 | std::unordered_map<std::string, std::shared_ptr<Devices::nvdevice>> devices; |
| 141 | 140 | ||
| 142 | EventInterface events_interface; | ||
| 143 | |||
| 144 | KernelHelpers::ServiceContext service_context; | 141 | KernelHelpers::ServiceContext service_context; |
| 145 | 142 | ||
| 143 | EventInterface events_interface; | ||
| 144 | |||
| 146 | void CreateEvent(u32 event_id); | 145 | void CreateEvent(u32 event_id); |
| 147 | void FreeEvent(u32 event_id); | 146 | void FreeEvent(u32 event_id); |
| 148 | }; | 147 | }; |
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp index 81ee28f31..bd41205b8 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp +++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: 2021 yuzu emulator team and Skyline Team and Contributors |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // (https://github.com/skyline-emu/) |
| 3 | // SPDX-License-Identifier: GPL-3.0-or-later Licensed under GPLv3 | ||
| 4 | // or any later version Refer to the license.txt file included. | ||
| 3 | 5 | ||
| 4 | #include <cinttypes> | 6 | #include <cinttypes> |
| 5 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |