From 00a77644192642e06462c11479a5c0e9bd859e9a Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 26 Mar 2026 16:35:32 +0100 Subject: kapi: extract interrupts API --- arch/x86_64/CMakeLists.txt | 2 +- arch/x86_64/kapi/cpu/interrupts.cpp | 67 ----------------------------------- arch/x86_64/kapi/interrupts.cpp | 68 ++++++++++++++++++++++++++++++++++++ arch/x86_64/src/cpu/interrupts.cpp | 3 +- kapi/CMakeLists.txt | 3 +- kapi/include/kapi/cpu.hpp | 1 - kapi/include/kapi/cpu/interrupts.hpp | 63 --------------------------------- kapi/include/kapi/interrupts.hpp | 61 ++++++++++++++++++++++++++++++++ kernel/src/main.cpp | 3 +- 9 files changed, 135 insertions(+), 136 deletions(-) delete mode 100644 arch/x86_64/kapi/cpu/interrupts.cpp create mode 100644 arch/x86_64/kapi/interrupts.cpp delete mode 100644 kapi/include/kapi/cpu/interrupts.hpp create mode 100644 kapi/include/kapi/interrupts.hpp diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt index 8ff81d8..4427e4c 100644 --- a/arch/x86_64/CMakeLists.txt +++ b/arch/x86_64/CMakeLists.txt @@ -15,7 +15,7 @@ target_sources("x86_64" PRIVATE "kapi/boot_modules.cpp" "kapi/cio.cpp" "kapi/cpu.cpp" - "kapi/cpu/interrupts.cpp" + "kapi/interrupts.cpp" "kapi/memory.cpp" "kapi/system.cpp" diff --git a/arch/x86_64/kapi/cpu/interrupts.cpp b/arch/x86_64/kapi/cpu/interrupts.cpp deleted file mode 100644 index b98595c..0000000 --- a/arch/x86_64/kapi/cpu/interrupts.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "kapi/cpu.hpp" -#include "kapi/system.hpp" - -#include -#include - -#include -#include - -namespace kapi::cpu -{ - - namespace - { - constexpr auto irq_offset = 32uz; - auto constinit interrupt_handlers = std::array, 256 - irq_offset>{}; - } // namespace - - auto enable_interrupts() -> void - { - asm volatile("sti"); - } - - auto disable_interrupts() -> void - { - asm volatile("cli"); - } - - auto register_interrupt_handler(std::uint32_t irq_number, interrupt_handler & handler) -> void - { - if (irq_number < irq_offset) - { - system::panic("[x86_64:CPU] IRQ number must be in range [32, 255]."); - } - - interrupt_handlers[irq_number - irq_offset].push_back(&handler); - } - - auto unregister_interrupt_handler(std::uint32_t irq_number, [[maybe_unused]] interrupt_handler & handler) -> void - { - if (irq_number < irq_offset) - { - system::panic("[x86_64:CPU] IRQ number must be in range [32, 255]."); - } - - kstd::println("[x86_64:CPU] TODO: support erasure from vector."); - } - - auto dispatch_interrupt(std::uint32_t irq_number) -> status - { - if (irq_number < irq_offset) - { - return status::unhandled; - } - - for (auto handler : interrupt_handlers[irq_number - irq_offset]) - { - if (handler && handler->handle_interrupt(irq_number) == status::handled) - { - return status::handled; - } - } - - return status::unhandled; - } - -} // namespace kapi::cpu \ No newline at end of file diff --git a/arch/x86_64/kapi/interrupts.cpp b/arch/x86_64/kapi/interrupts.cpp new file mode 100644 index 0000000..babc926 --- /dev/null +++ b/arch/x86_64/kapi/interrupts.cpp @@ -0,0 +1,68 @@ +#include "kapi/interrupts.hpp" + +#include "kapi/system.hpp" + +#include +#include + +#include +#include + +namespace kapi::interrupts +{ + + namespace + { + constexpr auto irq_offset = 32uz; + auto constinit handlers = std::array, 256 - irq_offset>{}; + } // namespace + + auto enable() -> void + { + asm volatile("sti"); + } + + auto disable() -> void + { + asm volatile("cli"); + } + + auto register_handler(std::uint32_t irq_number, handler & handler) -> void + { + if (irq_number < irq_offset) + { + system::panic("[x86_64:CPU] IRQ number must be in range [32, 255]."); + } + + handlers[irq_number - irq_offset].push_back(&handler); + } + + auto unregister_handler(std::uint32_t irq_number, [[maybe_unused]] handler & handler) -> void + { + if (irq_number < irq_offset) + { + system::panic("[x86_64:CPU] IRQ number must be in range [32, 255]."); + } + + kstd::println("[x86_64:CPU] TODO: support erasure from vector."); + } + + auto dispatch(std::uint32_t irq_number) -> status + { + if (irq_number < irq_offset) + { + return status::unhandled; + } + + for (auto handler : handlers[irq_number - irq_offset]) + { + if (handler && handler->handle_interrupt(irq_number) == status::handled) + { + return status::handled; + } + } + + return status::unhandled; + } + +} // namespace kapi::interrupts \ No newline at end of file diff --git a/arch/x86_64/src/cpu/interrupts.cpp b/arch/x86_64/src/cpu/interrupts.cpp index 9ee3ce8..2f23f07 100644 --- a/arch/x86_64/src/cpu/interrupts.cpp +++ b/arch/x86_64/src/cpu/interrupts.cpp @@ -1,6 +1,7 @@ #include "arch/cpu/interrupts.hpp" #include "kapi/cpu.hpp" +#include "kapi/interrupts.hpp" #include "kapi/memory.hpp" #include "arch/cpu/legacy_pic.hpp" @@ -146,7 +147,7 @@ namespace arch::cpu } } else if (number >= number_of_exception_vectors && - kapi::cpu::dispatch_interrupt(number) == kapi::cpu::status::unhandled) + kapi::interrupts::dispatch(number) == kapi::interrupts::status::unhandled) { kstd::println(kstd::print_sink::stderr, "[x86_64:CPU] Unhandled interrupt {:#04x}", number); } diff --git a/kapi/CMakeLists.txt b/kapi/CMakeLists.txt index 4c94829..99b737c 100644 --- a/kapi/CMakeLists.txt +++ b/kapi/CMakeLists.txt @@ -9,8 +9,7 @@ target_sources("kapi" PUBLIC "include/kapi/boot.hpp" "include/kapi/cio.hpp" "include/kapi/cpu.hpp" - "include/kapi/cpu/interrupts.hpp" - "include/kapi/cpu/exception.hpp" + "include/kapi/interrupts.hpp" "include/kapi/boot_module/boot_module.hpp" "include/kapi/boot_module/boot_module_registry.hpp" "include/kapi/memory.hpp" diff --git a/kapi/include/kapi/cpu.hpp b/kapi/include/kapi/cpu.hpp index 041a5db..c6aa6ff 100644 --- a/kapi/include/kapi/cpu.hpp +++ b/kapi/include/kapi/cpu.hpp @@ -1,7 +1,6 @@ #ifndef TEACHOS_KAPI_CPU_HPP #define TEACHOS_KAPI_CPU_HPP -#include "kapi/cpu/interrupts.hpp" // IWYU pragma: export #include "kapi/memory.hpp" #include diff --git a/kapi/include/kapi/cpu/interrupts.hpp b/kapi/include/kapi/cpu/interrupts.hpp deleted file mode 100644 index 328e4a7..0000000 --- a/kapi/include/kapi/cpu/interrupts.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef TEACHOS_KAPI_CPU_INTERRUPTS_HPP -#define TEACHOS_KAPI_CPU_INTERRUPTS_HPP - -// IWYU pragma: private, include "kapi/cpu.hpp" - -#include - -namespace kapi::cpu -{ - - enum class status : bool - { - unhandled, - handled, - }; - - //! The interface for all interrupt handlers. - struct interrupt_handler - { - virtual ~interrupt_handler() = default; - - //! Handle an interrupt with the given IRQ number. - // - //! This function will be called by the kernel in an interrupt context. As such, the function should complete its - //! task quickly and must take care when acquiring globally shared locks. - //! - //! @param irq_number The identifier of the interrupt request that triggered the handler. - //! @return status::handled if the handler successfully handled the interrupt, status::unhandled otherwise. - virtual auto handle_interrupt(std::uint32_t irq_number) -> status = 0; - }; - - //! @qualifier platform-defined - //! Enable external interrupts. - auto enable_interrupts() -> void; - - //! @qualifier platform-defined - //! Disable external interrupts. - auto disable_interrupts() -> void; - - //! @qualifier platform-defined - //! Register an interrupt handler for the given IRQ number. - //! - //! @param irq_number The IRQ number to register the handler for. - //! @param handler The interrupt handler to register. - auto register_interrupt_handler(std::uint32_t irq_number, interrupt_handler & handler) -> void; - - //! @qualifier platform-defined - //! Unregister a previously registered interrupt handler. - //! - //! @param irq_number The IRQ number to unregister the handler for. - //! @param handler The interrupt handler to unregister. - auto unregister_interrupt_handler(std::uint32_t irq_number, interrupt_handler & handler) -> void; - - //! @qualifier platform-defined - //! Dispatch an interrupt to all registered handlers. - //! - //! @param irq_number The IRQ number to dispatch. - //! @return status::handled if the interrupt was handled by at least one handler, status::unhandled otherwise. - auto dispatch_interrupt(std::uint32_t irq_number) -> status; - -} // namespace kapi::cpu - -#endif \ No newline at end of file diff --git a/kapi/include/kapi/interrupts.hpp b/kapi/include/kapi/interrupts.hpp new file mode 100644 index 0000000..fa4bc95 --- /dev/null +++ b/kapi/include/kapi/interrupts.hpp @@ -0,0 +1,61 @@ +#ifndef TEACHOS_KAPI_INTERRUPTS_HPP +#define TEACHOS_KAPI_INTERRUPTS_HPP + +#include + +namespace kapi::interrupts +{ + + enum class status : bool + { + unhandled, + handled, + }; + + //! The interface for all interrupt handlers. + struct handler + { + virtual ~handler() = default; + + //! Handle an interrupt with the given IRQ number. + // + //! This function will be called by the kernel in an interrupt context. As such, the function should complete its + //! task quickly and must take care when acquiring globally shared locks. + //! + //! @param irq_number The identifier of the interrupt request that triggered the handler. + //! @return status::handled if the handler successfully handled the interrupt, status::unhandled otherwise. + virtual auto handle_interrupt(std::uint32_t irq_number) -> status = 0; + }; + + //! @qualifier platform-defined + //! Enable external interrupts. + auto enable() -> void; + + //! @qualifier platform-defined + //! Disable external interrupts. + auto disable() -> void; + + //! @qualifier platform-defined + //! Register an interrupt handler for the given IRQ number. + //! + //! @param irq_number The IRQ number to register the handler for. + //! @param handler The interrupt handler to register. + auto register_handler(std::uint32_t irq_number, handler & handler) -> void; + + //! @qualifier platform-defined + //! Unregister a previously registered interrupt handler. + //! + //! @param irq_number The IRQ number to unregister the handler for. + //! @param handler The interrupt handler to unregister. + auto unregister_handler(std::uint32_t irq_number, handler & handler) -> void; + + //! @qualifier platform-defined + //! Dispatch an interrupt to all registered handlers. + //! + //! @param irq_number The IRQ number to dispatch. + //! @return status::handled if the interrupt was handled by at least one handler, status::unhandled otherwise. + auto dispatch(std::uint32_t irq_number) -> status; + +} // namespace kapi::interrupts + +#endif \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 45a4aae..6434045 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,6 +1,7 @@ #include "kapi/boot_modules.hpp" #include "kapi/cio.hpp" #include "kapi/cpu.hpp" +#include "kapi/interrupts.hpp" #include "kapi/memory.hpp" #include "kapi/system.hpp" @@ -92,7 +93,7 @@ auto main() -> int kstd::println("[OS] IO subsystem initialized."); kapi::cpu::init(); - kapi::cpu::enable_interrupts(); + kapi::interrupts::enable(); kapi::memory::init(); kernel::memory::init_heap(kapi::memory::heap_base); -- cgit v1.2.3