From b7fe08519f75c6e1aa3081db804bea9edfe6fcec Mon Sep 17 00:00:00 2001 From: "Daniel R." <47796739+polybiusproxy@users.noreply.github.com> Date: Thu, 31 Oct 2024 16:53:03 +0100 Subject: [PATCH] core/gnmdriver: Proper interrupt registering (#1218) --- .gitignore | 16 ++++---- src/core/libraries/gnmdriver/gnmdriver.cpp | 10 ++--- src/core/platform.h | 44 ++++++++++++---------- 3 files changed, 38 insertions(+), 32 deletions(-) diff --git a/.gitignore b/.gitignore index 9abc4aae..61d9e32e 100644 --- a/.gitignore +++ b/.gitignore @@ -382,13 +382,13 @@ FodyWeavers.xsd # VS Code files for those working on multiple tools .vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json +.vscode/settings.json +.vscode/tasks.json +.vscode/launch.json +.vscode/extensions.json *.code-workspace -/CMakeUserPresets.json -/compile_commands.json +/CMakeUserPresets.json +/compile_commands.json # Local History for Visual Studio Code .history/ @@ -411,6 +411,6 @@ FodyWeavers.xsd /out/* /third-party/out/* /src/common/scm_rev.cpp - + # for macOS -**/.DS_Store +**/.DS_Store diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index 4d8aa881..08f534c7 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -359,12 +359,13 @@ s32 PS4_SYSV_ABI sceGnmAddEqEvent(SceKernelEqueue eq, u64 id, void* udata) { eq->AddEvent(kernel_event); Platform::IrqC::Instance()->Register( - Platform::InterruptId::GfxEop, + static_cast<Platform::InterruptId>(id), [=](Platform::InterruptId irq) { - ASSERT_MSG(irq == Platform::InterruptId::GfxEop, + ASSERT_MSG(irq == static_cast<Platform::InterruptId>(id), "An unexpected IRQ occured"); // We need to convert IRQ# to event id and do // proper filtering in trigger function - eq->TriggerEvent(GnmEventIdents::GfxEop, SceKernelEvent::Filter::GraphicsCore, nullptr); + eq->TriggerEvent(static_cast<GnmEventIdents>(id), SceKernelEvent::Filter::GraphicsCore, + nullptr); }, eq); return ORBIS_OK; @@ -468,7 +469,6 @@ int PS4_SYSV_ABI sceGnmDebugHardwareStatus() { s32 PS4_SYSV_ABI sceGnmDeleteEqEvent(SceKernelEqueue eq, u64 id) { LOG_TRACE(Lib_GnmDriver, "called"); - ASSERT_MSG(id == GnmEventIdents::GfxEop); if (!eq) { return ORBIS_KERNEL_ERROR_EBADF; @@ -476,7 +476,7 @@ s32 PS4_SYSV_ABI sceGnmDeleteEqEvent(SceKernelEqueue eq, u64 id) { eq->RemoveEvent(id); - Platform::IrqC::Instance()->Unregister(Platform::InterruptId::GfxEop, eq); + Platform::IrqC::Instance()->Unregister(static_cast<Platform::InterruptId>(id), eq); return ORBIS_OK; } diff --git a/src/core/platform.h b/src/core/platform.h index 2c38dfd3..03bd79e8 100644 --- a/src/core/platform.h +++ b/src/core/platform.h @@ -17,31 +17,35 @@ namespace Platform { enum class InterruptId : u32 { - Compute0RelMem = 0u, - Compute1RelMem = 1u, - Compute2RelMem = 2u, - Compute3RelMem = 3u, - Compute4RelMem = 4u, - Compute5RelMem = 5u, - Compute6RelMem = 6u, - GfxEop = 7u, - GfxFlip = 8u, - GpuIdle = 9u, + Compute0RelMem = 0x00, + Compute1RelMem = 0x01, + Compute2RelMem = 0x02, + Compute3RelMem = 0x03, + Compute4RelMem = 0x04, + Compute5RelMem = 0x05, + Compute6RelMem = 0x06, + GfxEop = 0x40, + GfxFlip = 0x08, + GpuIdle = 0x09, + + InterruptIdMax = 0x40, ///< Max possible value (GfxEop) }; using IrqHandler = std::function<void(InterruptId)>; struct IrqController { void RegisterOnce(InterruptId irq, IrqHandler handler) { - ASSERT_MSG(static_cast<u32>(irq) < irq_contexts.size(), "Invalid IRQ number"); - auto& ctx = irq_contexts[static_cast<u32>(irq)]; + ASSERT_MSG(static_cast<u32>(irq) <= static_cast<u32>(InterruptId::InterruptIdMax), + "Invalid IRQ number"); + auto& ctx = irq_contexts.try_emplace(irq).first->second; std::unique_lock lock{ctx.m_lock}; ctx.one_time_subscribers.emplace(handler); } void Register(InterruptId irq, IrqHandler handler, void* uid) { - ASSERT_MSG(static_cast<u32>(irq) < irq_contexts.size(), "Invalid IRQ number"); - auto& ctx = irq_contexts[static_cast<u32>(irq)]; + ASSERT_MSG(static_cast<u32>(irq) <= static_cast<u32>(InterruptId::InterruptIdMax), + "Invalid IRQ number"); + auto& ctx = irq_contexts.try_emplace(irq).first->second; std::unique_lock lock{ctx.m_lock}; ASSERT_MSG(ctx.persistent_handlers.find(uid) == ctx.persistent_handlers.cend(), @@ -50,15 +54,17 @@ struct IrqController { } void Unregister(InterruptId irq, void* uid) { - ASSERT_MSG(static_cast<u32>(irq) < irq_contexts.size(), "Invalid IRQ number"); - auto& ctx = irq_contexts[static_cast<u32>(irq)]; + ASSERT_MSG(static_cast<u32>(irq) <= static_cast<u32>(InterruptId::InterruptIdMax), + "Invalid IRQ number"); + auto& ctx = irq_contexts.try_emplace(irq).first->second; std::unique_lock lock{ctx.m_lock}; ctx.persistent_handlers.erase(uid); } void Signal(InterruptId irq) { - ASSERT_MSG(static_cast<u32>(irq) < irq_contexts.size(), "Unexpected IRQ signaled"); - auto& ctx = irq_contexts[static_cast<u32>(irq)]; + ASSERT_MSG(static_cast<u32>(irq) <= static_cast<u32>(InterruptId::InterruptIdMax), + "Unexpected IRQ signaled"); + auto& ctx = irq_contexts.try_emplace(irq).first->second; std::unique_lock lock{ctx.m_lock}; LOG_TRACE(Core, "IRQ signaled: {}", magic_enum::enum_name(irq)); @@ -81,7 +87,7 @@ private: std::queue<IrqHandler> one_time_subscribers{}; std::mutex m_lock{}; }; - std::array<IrqContext, magic_enum::enum_count<InterruptId>()> irq_contexts{}; + std::unordered_map<InterruptId, IrqContext> irq_contexts{}; }; using IrqC = Common::Singleton<IrqController>;