diff options
Diffstat (limited to 'kapi')
| -rw-r--r-- | kapi/CMakeLists.txt | 15 | ||||
| -rw-r--r-- | kapi/include/kapi/cpu.hpp | 104 | ||||
| -rw-r--r-- | kapi/include/kapi/interrupts.hpp | 61 |
3 files changed, 168 insertions, 12 deletions
diff --git a/kapi/CMakeLists.txt b/kapi/CMakeLists.txt index b239adb..c9aa23f 100644 --- a/kapi/CMakeLists.txt +++ b/kapi/CMakeLists.txt @@ -1,22 +1,13 @@ add_library("kapi" INTERFACE) add_library("os::kapi" ALIAS "kapi") +file(GLOB_RECURSE KAPI_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "include/**.hpp") + target_sources("kapi" PUBLIC FILE_SET HEADERS BASE_DIRS "include" FILES - "include/kapi/boot_modules.hpp" - "include/kapi/boot.hpp" - "include/kapi/cio.hpp" - "include/kapi/boot_module/boot_module.hpp" - "include/kapi/boot_module/boot_module_registry.hpp" - "include/kapi/memory.hpp" - "include/kapi/memory/address.hpp" - "include/kapi/memory/frame_allocator.hpp" - "include/kapi/memory/frame.hpp" - "include/kapi/memory/page_mapper.hpp" - "include/kapi/memory/page.hpp" - "include/kapi/system.hpp" + ${KAPI_HEADERS} ) target_include_directories("kapi" INTERFACE diff --git a/kapi/include/kapi/cpu.hpp b/kapi/include/kapi/cpu.hpp index 05b84b7..c6aa6ff 100644 --- a/kapi/include/kapi/cpu.hpp +++ b/kapi/include/kapi/cpu.hpp @@ -1,13 +1,117 @@ #ifndef TEACHOS_KAPI_CPU_HPP #define TEACHOS_KAPI_CPU_HPP +#include "kapi/memory.hpp" + +#include <kstd/format> + +#include <cstdint> + namespace kapi::cpu { + + //! An exception originating from the CPU directly. + //! + //! Exception generally model interrupts that are synchronous to the instruction stream. This means that they do not + //! originate from external hardware, but rather are a product of program execution. + struct exception + { + //! The type of the exception, which identifies the reason for it being raised. + enum class type : std::uint8_t + { + //! The reason for the exception is unknown or platform-specific + unknown, + //! A page fault occurred + page_fault, + //! A memory access (either in the data or instruction stream) violated it's alignment constraints. + alignment_fault, + //! A memory access (either in the data or instruction stream) violated it's permissions. + memory_access_fault, + //! An invalid instruction was present in the instruction stream. + illegal_instruction, + //! The preconditions for the execution of an instruction were not met. + privilege_violation, + //! An arithmetic error occurred. + arithmetic_error, + //! A breakpoint was hit in the instruction stream. + breakpoint, + //! The CPU is single-stepping through the instruction stream. + single_step, + }; + + //! The type of this exception. + type type{}; + + //! The value of the instruction pointer at the time this exception was raised. + kapi::memory::linear_address instruction_pointer{}; + + //! The memory address that caused this exception. + kapi::memory::linear_address access_address{}; + + //! Whether the page was present at the time of the exception. + bool is_present{}; + + //! Whether the exception was caused by a write access. + bool is_write_access{}; + + //! Whether the exception was caused by a user mode access. + bool is_user_mode{}; + }; + //! @qualifier platform-defined //! Halt the CPU. //! //! This function terminates execution of the kernel. [[noreturn]] auto halt() -> void; + + //! @qualifier platform-defined + //! Perform early CPU initialization. + //! + //! When this function returns, the CPU is in a state where interrupt could be enabled. This function must not enable + //! interrupts itself. + auto init() -> void; + + //! @qualifier kernel-defined + //! Dispatch an exception to the appropriate handler. + //! + //! @param context The exception context. + //! @return Whether the exception was handled. + [[nodiscard]] auto dispatch(exception const & context) -> bool; + } // namespace kapi::cpu +template<> +struct kstd::formatter<enum kapi::cpu::exception::type> +{ + constexpr auto parse(kstd::format_parse_context & ctx) -> decltype(ctx.begin()) + { + return ctx.begin(); + } + + constexpr auto format(enum kapi::cpu::exception::type type, kstd::format_context & ctx) const -> void + { + switch (type) + { + case kapi::cpu::exception::type::unknown: + return ctx.push("unknown"); + case kapi::cpu::exception::type::page_fault: + return ctx.push("page fault"); + case kapi::cpu::exception::type::alignment_fault: + return ctx.push("alignment fault"); + case kapi::cpu::exception::type::memory_access_fault: + return ctx.push("memory access fault"); + case kapi::cpu::exception::type::illegal_instruction: + return ctx.push("illegal instruction"); + case kapi::cpu::exception::type::privilege_violation: + return ctx.push("privilege violation"); + case kapi::cpu::exception::type::arithmetic_error: + return ctx.push("arithmetic error"); + case kapi::cpu::exception::type::breakpoint: + return ctx.push("breakpoint"); + case kapi::cpu::exception::type::single_step: + return ctx.push("single step"); + } + } +}; + #endif diff --git a/kapi/include/kapi/interrupts.hpp b/kapi/include/kapi/interrupts.hpp new file mode 100644 index 0000000..f72ef8c --- /dev/null +++ b/kapi/include/kapi/interrupts.hpp @@ -0,0 +1,61 @@ +#ifndef TEACHOS_KAPI_INTERRUPTS_HPP +#define TEACHOS_KAPI_INTERRUPTS_HPP + +#include <cstdint> + +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 kernel-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 kernel-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 kernel-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 |
