mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-02-13 17:10:08 +00:00
core/gnmdriver: Proper interrupt registering (#1218)
This commit is contained in:
parent
72440a4996
commit
b7fe08519f
16
.gitignore
vendored
16
.gitignore
vendored
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>;
|
||||||
|
|
Loading…
Reference in a new issue