core/gnmdriver: Proper interrupt registering ()

This commit is contained in:
Daniel R. 2024-10-31 16:53:03 +01:00 committed by GitHub
parent 72440a4996
commit b7fe08519f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 38 additions and 32 deletions
.gitignore
src/core
libraries/gnmdriver
platform.h

16
.gitignore vendored
View file

@ -382,13 +382,13 @@ FodyWeavers.xsd
# VS Code files for those working on multiple tools # VS Code files for those working on multiple tools
.vscode/* .vscode/*
!.vscode/settings.json .vscode/settings.json
!.vscode/tasks.json .vscode/tasks.json
!.vscode/launch.json .vscode/launch.json
!.vscode/extensions.json .vscode/extensions.json
*.code-workspace *.code-workspace
/CMakeUserPresets.json /CMakeUserPresets.json
/compile_commands.json /compile_commands.json
# Local History for Visual Studio Code # Local History for Visual Studio Code
.history/ .history/
@ -411,6 +411,6 @@ FodyWeavers.xsd
/out/* /out/*
/third-party/out/* /third-party/out/*
/src/common/scm_rev.cpp /src/common/scm_rev.cpp
# for macOS # for macOS
**/.DS_Store **/.DS_Store

View file

@ -359,12 +359,13 @@ s32 PS4_SYSV_ABI sceGnmAddEqEvent(SceKernelEqueue eq, u64 id, void* udata) {
eq->AddEvent(kernel_event); eq->AddEvent(kernel_event);
Platform::IrqC::Instance()->Register( Platform::IrqC::Instance()->Register(
Platform::InterruptId::GfxEop, static_cast<Platform::InterruptId>(id),
[=](Platform::InterruptId irq) { [=](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 "An unexpected IRQ occured"); // We need to convert IRQ# to event id and do
// proper filtering in trigger function // proper filtering in trigger function
eq->TriggerEvent(GnmEventIdents::GfxEop, SceKernelEvent::Filter::GraphicsCore, nullptr); eq->TriggerEvent(static_cast<GnmEventIdents>(id), SceKernelEvent::Filter::GraphicsCore,
nullptr);
}, },
eq); eq);
return ORBIS_OK; return ORBIS_OK;
@ -468,7 +469,6 @@ int PS4_SYSV_ABI sceGnmDebugHardwareStatus() {
s32 PS4_SYSV_ABI sceGnmDeleteEqEvent(SceKernelEqueue eq, u64 id) { s32 PS4_SYSV_ABI sceGnmDeleteEqEvent(SceKernelEqueue eq, u64 id) {
LOG_TRACE(Lib_GnmDriver, "called"); LOG_TRACE(Lib_GnmDriver, "called");
ASSERT_MSG(id == GnmEventIdents::GfxEop);
if (!eq) { if (!eq) {
return ORBIS_KERNEL_ERROR_EBADF; return ORBIS_KERNEL_ERROR_EBADF;
@ -476,7 +476,7 @@ s32 PS4_SYSV_ABI sceGnmDeleteEqEvent(SceKernelEqueue eq, u64 id) {
eq->RemoveEvent(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; return ORBIS_OK;
} }

View file

@ -17,31 +17,35 @@
namespace Platform { namespace Platform {
enum class InterruptId : u32 { enum class InterruptId : u32 {
Compute0RelMem = 0u, Compute0RelMem = 0x00,
Compute1RelMem = 1u, Compute1RelMem = 0x01,
Compute2RelMem = 2u, Compute2RelMem = 0x02,
Compute3RelMem = 3u, Compute3RelMem = 0x03,
Compute4RelMem = 4u, Compute4RelMem = 0x04,
Compute5RelMem = 5u, Compute5RelMem = 0x05,
Compute6RelMem = 6u, Compute6RelMem = 0x06,
GfxEop = 7u, GfxEop = 0x40,
GfxFlip = 8u, GfxFlip = 0x08,
GpuIdle = 9u, GpuIdle = 0x09,
InterruptIdMax = 0x40, ///< Max possible value (GfxEop)
}; };
using IrqHandler = std::function<void(InterruptId)>; using IrqHandler = std::function<void(InterruptId)>;
struct IrqController { struct IrqController {
void RegisterOnce(InterruptId irq, IrqHandler handler) { void RegisterOnce(InterruptId irq, IrqHandler handler) {
ASSERT_MSG(static_cast<u32>(irq) < irq_contexts.size(), "Invalid IRQ number"); ASSERT_MSG(static_cast<u32>(irq) <= static_cast<u32>(InterruptId::InterruptIdMax),
auto& ctx = irq_contexts[static_cast<u32>(irq)]; "Invalid IRQ number");
auto& ctx = irq_contexts.try_emplace(irq).first->second;
std::unique_lock lock{ctx.m_lock}; std::unique_lock lock{ctx.m_lock};
ctx.one_time_subscribers.emplace(handler); ctx.one_time_subscribers.emplace(handler);
} }
void Register(InterruptId irq, IrqHandler handler, void* uid) { void Register(InterruptId irq, IrqHandler handler, void* uid) {
ASSERT_MSG(static_cast<u32>(irq) < irq_contexts.size(), "Invalid IRQ number"); ASSERT_MSG(static_cast<u32>(irq) <= static_cast<u32>(InterruptId::InterruptIdMax),
auto& ctx = irq_contexts[static_cast<u32>(irq)]; "Invalid IRQ number");
auto& ctx = irq_contexts.try_emplace(irq).first->second;
std::unique_lock lock{ctx.m_lock}; std::unique_lock lock{ctx.m_lock};
ASSERT_MSG(ctx.persistent_handlers.find(uid) == ctx.persistent_handlers.cend(), ASSERT_MSG(ctx.persistent_handlers.find(uid) == ctx.persistent_handlers.cend(),
@ -50,15 +54,17 @@ struct IrqController {
} }
void Unregister(InterruptId irq, void* uid) { void Unregister(InterruptId irq, void* uid) {
ASSERT_MSG(static_cast<u32>(irq) < irq_contexts.size(), "Invalid IRQ number"); ASSERT_MSG(static_cast<u32>(irq) <= static_cast<u32>(InterruptId::InterruptIdMax),
auto& ctx = irq_contexts[static_cast<u32>(irq)]; "Invalid IRQ number");
auto& ctx = irq_contexts.try_emplace(irq).first->second;
std::unique_lock lock{ctx.m_lock}; std::unique_lock lock{ctx.m_lock};
ctx.persistent_handlers.erase(uid); ctx.persistent_handlers.erase(uid);
} }
void Signal(InterruptId irq) { void Signal(InterruptId irq) {
ASSERT_MSG(static_cast<u32>(irq) < irq_contexts.size(), "Unexpected IRQ signaled"); ASSERT_MSG(static_cast<u32>(irq) <= static_cast<u32>(InterruptId::InterruptIdMax),
auto& ctx = irq_contexts[static_cast<u32>(irq)]; "Unexpected IRQ signaled");
auto& ctx = irq_contexts.try_emplace(irq).first->second;
std::unique_lock lock{ctx.m_lock}; std::unique_lock lock{ctx.m_lock};
LOG_TRACE(Core, "IRQ signaled: {}", magic_enum::enum_name(irq)); LOG_TRACE(Core, "IRQ signaled: {}", magic_enum::enum_name(irq));
@ -81,7 +87,7 @@ private:
std::queue<IrqHandler> one_time_subscribers{}; std::queue<IrqHandler> one_time_subscribers{};
std::mutex m_lock{}; 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>; using IrqC = Common::Singleton<IrqController>;