From 9bbf513c270a094b95563f4ecfd3d19c9088750d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Holz?= Date: Sat, 20 Jan 2024 18:18:31 +0100 Subject: [PATCH] Kernel/riscv64: Implement initialize_interrupts() --- Kernel/Arch/riscv64/InterruptManagement.cpp | 4 +- Kernel/Arch/riscv64/Interrupts.cpp | 75 +++++++++++++++++++-- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/Kernel/Arch/riscv64/InterruptManagement.cpp b/Kernel/Arch/riscv64/InterruptManagement.cpp index d6c9bd5250..c7c0c92495 100644 --- a/Kernel/Arch/riscv64/InterruptManagement.cpp +++ b/Kernel/Arch/riscv64/InterruptManagement.cpp @@ -37,9 +37,9 @@ void InterruptManagement::find_controllers() TODO_RISCV64(); } -u8 InterruptManagement::acquire_mapped_interrupt_number(u8) +u8 InterruptManagement::acquire_mapped_interrupt_number(u8 original_irq) { - TODO_RISCV64(); + return original_irq; } Vector> const& InterruptManagement::controllers() diff --git a/Kernel/Arch/riscv64/Interrupts.cpp b/Kernel/Arch/riscv64/Interrupts.cpp index 48455d1586..fea58b5d7e 100644 --- a/Kernel/Arch/riscv64/Interrupts.cpp +++ b/Kernel/Arch/riscv64/Interrupts.cpp @@ -11,9 +11,14 @@ #include #include #include +#include +#include namespace Kernel { +// FIXME: Share this array with x86_64/aarch64 somehow and consider if this really needs to use raw pointers and not OwnPtrs +static Array s_interrupt_handlers; + void dump_registers(RegisterState const&) { } @@ -32,18 +37,80 @@ ErrorOr reserve_interrupt_handlers(u8) TODO_RISCV64(); } -void register_generic_interrupt_handler(u8, GenericInterruptHandler&) +static void revert_to_unused_handler(u8 interrupt_number) { - TODO_RISCV64(); + auto* handler = new UnhandledInterruptHandler(interrupt_number); + handler->register_interrupt_handler(); } -void unregister_generic_interrupt_handler(u8, GenericInterruptHandler&) +// FIXME: Share the code below with Arch/{x86_64,aarch64}/Interrupts.cpp +void register_generic_interrupt_handler(u8 interrupt_number, GenericInterruptHandler& handler) { + auto*& handler_slot = s_interrupt_handlers[interrupt_number]; + if (handler_slot == nullptr) { + handler_slot = &handler; + return; + } + if (handler_slot->type() == HandlerType::UnhandledInterruptHandler) { + auto* unhandled_handler = static_cast(handler_slot); + unhandled_handler->unregister_interrupt_handler(); + delete unhandled_handler; + handler_slot = &handler; + return; + } + if (handler_slot->is_shared_handler()) { + VERIFY(handler_slot->type() == HandlerType::SharedIRQHandler); + static_cast(handler_slot)->register_handler(handler); + return; + } + if (!handler_slot->is_shared_handler()) { + if (handler_slot->type() == HandlerType::SpuriousInterruptHandler) { + // FIXME: Add support for spurious interrupts on riscv64 + TODO_RISCV64(); + } + VERIFY(handler_slot->type() == HandlerType::IRQHandler); + auto& previous_handler = *handler_slot; + handler_slot = nullptr; + SharedIRQHandler::initialize(interrupt_number); + VERIFY(handler_slot); + static_cast(handler_slot)->register_handler(previous_handler); + static_cast(handler_slot)->register_handler(handler); + return; + } + VERIFY_NOT_REACHED(); +} + +// FIXME: Share the code below with Arch/{x86_64,aarch64}/Interrupts.cpp +void unregister_generic_interrupt_handler(u8 interrupt_number, GenericInterruptHandler& handler) +{ + auto*& handler_slot = s_interrupt_handlers[interrupt_number]; + VERIFY(handler_slot != nullptr); + if (handler_slot->type() == HandlerType::UnhandledInterruptHandler) + return; + if (handler_slot->is_shared_handler()) { + VERIFY(handler_slot->type() == HandlerType::SharedIRQHandler); + auto* shared_handler = static_cast(handler_slot); + shared_handler->unregister_handler(handler); + if (shared_handler->sharing_devices_count() == 0) { + handler_slot = nullptr; + revert_to_unused_handler(interrupt_number); + } + return; + } + if (!handler_slot->is_shared_handler()) { + VERIFY(handler_slot->type() == HandlerType::IRQHandler); + handler_slot = nullptr; + revert_to_unused_handler(interrupt_number); + return; + } } void initialize_interrupts() { - TODO_RISCV64(); + for (size_t i = 0; i < s_interrupt_handlers.size(); ++i) { + auto* handler = new UnhandledInterruptHandler(i); + handler->register_interrupt_handler(); + } } }