aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-03-30 11:20:08 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-03-30 11:20:08 +0200
commit706f529722520429860ce60237d4ef71b2b27601 (patch)
treea5a4e89ae3ed25b0af521249134e524a0142814f /arch/x86_64
parent2864e0b061f923a3c73c608b9c27ca4a7116e27c (diff)
parent3070bb45b9741165d786b2c5a018ee55c1a82db8 (diff)
downloadkernel-706f529722520429860ce60237d4ef71b2b27601.tar.xz
kernel-706f529722520429860ce60237d4ef71b2b27601.zip
Merge branch 'fmorgner/interrupt-handling' into develop-BA-FS26
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/CMakeLists.txt1
-rw-r--r--arch/x86_64/include/arch/cpu/interrupts.hpp49
-rw-r--r--arch/x86_64/kapi/cpu.cpp19
-rw-r--r--arch/x86_64/kapi/interrupts.cpp16
-rw-r--r--arch/x86_64/kapi/system.cpp10
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp69
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp81
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp24
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp40
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp45
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp105
-rw-r--r--arch/x86_64/pre/include/arch/interrupt_handling/generic_interrupt_handler.hpp34
-rw-r--r--arch/x86_64/pre/include/arch/kernel/cpu/call.hpp30
-rw-r--r--arch/x86_64/pre/include/arch/kernel/cpu/idtr.hpp27
-rw-r--r--arch/x86_64/pre/include/arch/kernel/cpu/if.hpp21
-rw-r--r--arch/x86_64/pre/include/arch/kernel/cpu/msr.hpp64
-rw-r--r--arch/x86_64/pre/include/arch/kernel/cpu/tr.hpp24
-rw-r--r--arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/gate_descriptor.cpp24
-rw-r--r--arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/idt_flags.cpp20
-rw-r--r--arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp53
-rw-r--r--arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.cpp13
-rw-r--r--arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/ist_offset.cpp10
-rw-r--r--arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/segment_selector.cpp24
-rw-r--r--arch/x86_64/pre/src/interrupt_handling/generic_interrupt_handler.cpp13
-rw-r--r--arch/x86_64/pre/src/kernel/cpu/call.cpp9
-rw-r--r--arch/x86_64/pre/src/kernel/cpu/idtr.cpp18
-rw-r--r--arch/x86_64/pre/src/kernel/cpu/if.cpp13
-rw-r--r--arch/x86_64/pre/src/kernel/cpu/tr.cpp16
-rw-r--r--arch/x86_64/src/cpu/interrupts.cpp177
29 files changed, 189 insertions, 860 deletions
diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt
index 89d9bc0..4427e4c 100644
--- a/arch/x86_64/CMakeLists.txt
+++ b/arch/x86_64/CMakeLists.txt
@@ -15,6 +15,7 @@ target_sources("x86_64" PRIVATE
"kapi/boot_modules.cpp"
"kapi/cio.cpp"
"kapi/cpu.cpp"
+ "kapi/interrupts.cpp"
"kapi/memory.cpp"
"kapi/system.cpp"
diff --git a/arch/x86_64/include/arch/cpu/interrupts.hpp b/arch/x86_64/include/arch/cpu/interrupts.hpp
index 8f156a4..b9adb6e 100644
--- a/arch/x86_64/include/arch/cpu/interrupts.hpp
+++ b/arch/x86_64/include/arch/cpu/interrupts.hpp
@@ -1,6 +1,8 @@
#ifndef TEACHOS_X86_64_CPU_INTERRUPTS_HPP
#define TEACHOS_X86_64_CPU_INTERRUPTS_HPP
+#include "kapi/memory.hpp"
+
#include "arch/cpu/segment_selector.hpp"
#include <array>
@@ -57,36 +59,36 @@ namespace arch::cpu
{
struct
{
- std::uint64_t r15;
- std::uint64_t r14;
- std::uint64_t r13;
- std::uint64_t r12;
- std::uint64_t r11;
- std::uint64_t r10;
- std::uint64_t r9;
- std::uint64_t r8;
- std::uint64_t rdi;
- std::uint64_t rsi;
- std::uint64_t rbp;
- std::uint64_t rdx;
- std::uint64_t rcx;
- std::uint64_t rbx;
- std::uint64_t rax;
+ std::uint64_t r15{};
+ std::uint64_t r14{};
+ std::uint64_t r13{};
+ std::uint64_t r12{};
+ std::uint64_t r11{};
+ std::uint64_t r10{};
+ std::uint64_t r9{};
+ std::uint64_t r8{};
+ std::uint64_t rdi{};
+ std::uint64_t rsi{};
+ std::uint64_t rbp{};
+ std::uint64_t rdx{};
+ std::uint64_t rcx{};
+ std::uint64_t rbx{};
+ std::uint64_t rax{};
} handler_saved;
struct
{
- std::uint64_t number;
- std::uint64_t error_code;
+ std::uint64_t number{};
+ std::uint64_t error_code{};
} interrupt;
struct
{
- std::uint64_t rip;
- std::uint64_t cs;
- std::uint64_t rflags;
- std::uint64_t rsp;
- std::uint64_t ss;
+ kapi::memory::linear_address rip{};
+ std::uint64_t cs{};
+ std::uint64_t rflags{};
+ kapi::memory::linear_address rsp{};
+ std::uint64_t ss{};
} cpu_saved;
};
@@ -109,9 +111,6 @@ namespace arch::cpu
auto static read() -> interrupt_descriptor_table_register;
};
- auto enable_interrupts() -> void;
- auto disable_interrupts() -> void;
-
} // namespace arch::cpu
#endif \ No newline at end of file
diff --git a/arch/x86_64/kapi/cpu.cpp b/arch/x86_64/kapi/cpu.cpp
index 2a0f8f7..12edb0f 100644
--- a/arch/x86_64/kapi/cpu.cpp
+++ b/arch/x86_64/kapi/cpu.cpp
@@ -1,8 +1,27 @@
#include "kapi/cpu.hpp"
+#include "kapi/system.hpp"
+
+#include "arch/cpu/initialization.hpp"
+
+#include <atomic>
+
namespace kapi::cpu
{
+ auto init() -> void
+ {
+ auto static constinit is_initialized = std::atomic_flag{};
+
+ if (is_initialized.test_and_set())
+ {
+ system::panic("[x86_64] CPU has already been initialized.");
+ }
+
+ arch::cpu::initialize_descriptors();
+ arch::cpu::initialize_legacy_interrupts();
+ }
+
auto halt() -> void
{
asm volatile("1: hlt\njmp 1b");
diff --git a/arch/x86_64/kapi/interrupts.cpp b/arch/x86_64/kapi/interrupts.cpp
new file mode 100644
index 0000000..cf1defa
--- /dev/null
+++ b/arch/x86_64/kapi/interrupts.cpp
@@ -0,0 +1,16 @@
+#include "kapi/interrupts.hpp"
+
+namespace kapi::interrupts
+{
+
+ auto enable() -> void
+ {
+ asm volatile("sti");
+ }
+
+ auto disable() -> void
+ {
+ asm volatile("cli");
+ }
+
+} // namespace kapi::interrupts \ No newline at end of file
diff --git a/arch/x86_64/kapi/system.cpp b/arch/x86_64/kapi/system.cpp
index 301169f..09c7152 100644
--- a/arch/x86_64/kapi/system.cpp
+++ b/arch/x86_64/kapi/system.cpp
@@ -1,16 +1,8 @@
#include "kapi/system.hpp"
-#include "arch/cpu/initialization.hpp"
-#include "arch/cpu/interrupts.hpp"
-
namespace kapi::system
{
- auto memory_initialized() -> void
- {
- arch::cpu::initialize_descriptors();
- arch::cpu::initialize_legacy_interrupts();
- arch::cpu::enable_interrupts();
- }
+ auto memory_initialized() -> void {}
} // namespace kapi::system \ No newline at end of file
diff --git a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp
deleted file mode 100644
index 07110c8..0000000
--- a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP
-#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP
-
-#include "arch/context_switching/interrupt_descriptor_table/idt_flags.hpp"
-#include "arch/context_switching/interrupt_descriptor_table/ist_offset.hpp"
-#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp"
-
-#include <bitset>
-#include <cstdint>
-
-namespace teachos::arch::context_switching::interrupt_descriptor_table
-{
- __extension__ typedef __int128 int128_t;
- __extension__ typedef unsigned __int128 uint128_t;
-
- /**
- * @brief Defines helper function for all states and the actual data the gate descriptor can have.
- */
- struct [[gnu::packed]] gate_descriptor
- {
- /**
- * @brief Default Constructor.
- */
- gate_descriptor() = default;
-
- /**
- * @brief Constructor.
- *
- * @note Created gate descriptor copies the given bytes into these components ending with a 32 bit reserved
- * field that has to be used, because the 64-bit gate descriptor needs to be big enough for two 32-bit gate
- * descriptor.
- * - 16 bit Segment Selector
- * - 3 bit Interrupt Stack Table Offset
- * - 8 bit Type and Flags
- * - 64 bit Offset
- *
- * @param flags Copies the bits set from the given data into the individual components of a gate
- * descriptor.
- */
- explicit gate_descriptor(uint128_t flags);
-
- /**
- * @brief Constructor.
- *
- * @param selector, ist, flags, offset Copies the bits set from the given data into the individual components of
- * a gate descriptor.
- */
- gate_descriptor(segment_selector selector, ist_offset ist, idt_flags flags, uint64_t offset);
-
- /**
- * @brief Allows to compare the underlying bits of two instances.
- *
- * @param other Other instance that we want to compare with.
- * @return Whether the underlying set bits of both types are the same.
- */
- auto operator==(gate_descriptor const & other) const -> bool = default;
-
- private:
- // The order in private variables starts for the first variable being the rightmost bit.
- uint16_t _offset_1 = {}; ///< Lower 16 bits of handler function address (0 - 15)
- segment_selector _selector = {}; ///< Segment selector (16 - 31)
- ist_offset _ist = {}; ///< Interrupt Stack Table offset (32 - 39)
- idt_flags _flags = {}; ///< Gate Type and Flags (40 - 47)
- uint64_t _offset_2 : 48 = {}; ///< Upper 48 bits of handler function address (48 - 95)
- uint32_t : 32; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127)
- };
-} // namespace teachos::arch::context_switching::interrupt_descriptor_table
-
-#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp
deleted file mode 100644
index 5104c36..0000000
--- a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp
+++ /dev/null
@@ -1,81 +0,0 @@
-
-#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IDT_FLAGS_HPP
-#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IDT_FLAGS_HPP
-
-#include <bitset>
-#include <cstdint>
-
-namespace teachos::arch::context_switching::interrupt_descriptor_table
-{
- /**
- * @brief Defines helper function for all states that the access byte field of a segment descriptor can
- * have.
- */
- struct [[gnu::packed]] idt_flags
- {
- /**
- * @brief Possible set bits in our underlying bits and the meaning when they are set.
- */
- enum bitset : uint8_t
- {
- INTERRUPT_GATE = 0b01110, ///< The actual type of gate segment is a interrupt gate.
- TRAP_GATE = 0b01111, ///< The actual type of gate segment is a trap gate.
- DESCRIPTOR_LEVEL_KERNEL =
- 0U << 5U, ///< Highest privileged level used by the kernel to allow for full access of resources.
- DESCRIPTOR_LEVEL_ADMIN =
- 1U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more
- ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended.
- DESCRIPTOR_LEVEL_PRIVILEGED_USER =
- 2U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more
- ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended.
- DESCRIPTOR_LEVEL_USER = 3U << 5U, ///< Restricts access to only application and their specific memory.
- PRESENT = 1U << 7U, ///< Present bit; Allows an entry to refer to a valid segment.
- ///< Must be set (1) for any valid segment.
- };
-
- /**
- * @brief Default Constructor.
- */
- idt_flags() = default;
-
- /**
- * @brief Constructor.
- *
- * @param flags Allows to set flags for the access byte field using the unscoped enum contained in this class, used
- * to allow for direct integer conversion. This value is saved and can later be used to check whether certain flags
- * are enabled or not using contains_flags method.
- */
- idt_flags(uint8_t flags);
-
- /**
- * @brief Checks if the given std::bitset is a subset or equivalent to the underlying data.
- *
- * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng
- * data. Any additional bits that are set are not relevant.
- *
- * @param other Flags that we want to compare against and check if the underlying data has the same bits set.
- * @return Whether the given flags are a subset or equivalent with the underlying data.
- */
- auto contains_flags(std::bitset<8U> other) const -> bool;
-
- /**
- * @brief Allows to compare the underlying bits of two instances.
- *
- * @param other Other instance that we want to compare with.
- * @return Whether the underlying set bits of both types are the same.
- */
- auto operator==(idt_flags const & other) const -> bool = default;
-
- /**
- * @brief Combines all bits that are set in the std::bitset flags with the bits already set in the underlying data.
- *
- * @param other Additional bits that should be set.
- */
- auto operator|=(std::bitset<8U> other) -> void;
-
- private:
- uint8_t _flags = {}; ///< Underlying bits used to read the flags from.
- };
-} // namespace teachos::arch::context_switching::interrupt_descriptor_table
-
-#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IDT_FLAGS_HPP \ No newline at end of file
diff --git a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp
deleted file mode 100644
index b388e0e..0000000
--- a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP
-#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP
-
-#include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp"
-
-namespace teachos::arch::context_switching::interrupt_descriptor_table
-{
- /**
- * @brief Updates the IDTR with the created interrupt descriptor table. If it has not been created yet this
- * method will create it.
- */
- auto update_interrupt_descriptor_table_register() -> void;
-
- /**
- * @brief Creates the interrupt descriptor table, with the minimum required configuration. If this method is called
- * more than once, the previously created instance is returned instead.
- *
- * @return Reference to the created interrupt_descriptor_table.
- */
- auto get_or_create_interrupt_descriptor_table() -> interrupt_descriptor_table &;
-
-} // namespace teachos::arch::context_switching::interrupt_descriptor_table
-
-#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp
deleted file mode 100644
index 7fe933b..0000000
--- a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP
-#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP
-
-#include "arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp"
-#include "arch/stl/vector.hpp"
-
-namespace teachos::arch::context_switching::interrupt_descriptor_table
-{
- using interrupt_descriptor_table = stl::vector<gate_descriptor>;
-
- /**
- * @brief Represents a pointer to the Interrupt Descriptor Table (IDT).
- *
- * This structure is used to store the base address and length of the IDT.
- */
- struct [[gnu::packed]] interrupt_descriptor_table_pointer
- {
- /**
- * @brief Default constructor.
- */
- interrupt_descriptor_table_pointer() = default;
-
- /**
- * @brief Constructor.
- */
- interrupt_descriptor_table_pointer(uint16_t table_length, gate_descriptor * address);
-
- /**
- * @brief Defaulted three-way comparsion operator.
- */
- auto operator<=>(interrupt_descriptor_table_pointer const & other) const -> std::strong_ordering = default;
-
- private:
- uint16_t table_length = {}; ///< The amount of segment descriptor entries in the global descriptor table - 1.
- gate_descriptor * address = {}; ///< Non-owning pointer to the IDT base address.
- };
-
-} // namespace teachos::arch::context_switching::interrupt_descriptor_table
-
-#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp
deleted file mode 100644
index e45bcf4..0000000
--- a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IST_OFFSET_HPP
-#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IST_OFFSET_HPP
-
-#include <bitset>
-#include <cstdint>
-
-namespace teachos::arch::context_switching::interrupt_descriptor_table
-{
- /**
- * @brief Defines helper function for all states that the interrupt stack table offset field of a gate descriptor can
- * have. Is automatically increased to one byte in size, to include the following 5 reserved bits in the gate
- * descriptor.
- */
- struct [[gnu::packed]] ist_offset
- {
- /**
- * @brief Default Constructor.
- */
- ist_offset() = default;
-
- /**
- * @brief Constructor.
- *
- * @param offset Offset into the interrupt stack table. A value of of 0 means we do not switch stacks, whereas 1 - 7
- * mean we switch to the n-th stack in the Interrupt Stack Table, contained in the TSS if the gate descriptor that
- * contains this field is called.
- */
- ist_offset(uint8_t offset);
-
- /**
- * @brief Allows to compare the underlying set bits of two instances.
- *
- * @param other Other instance that we want to compare with.
- * @return Whether the underlying set bits of both types are the same.
- */
- auto operator==(ist_offset const & other) const -> bool = default;
-
- private:
- uint8_t _ist : 3 = {}; ///< Offset into the interrupt stack table. A value of of 0 means we do not switch stacks,
- ///< whereas 1 - 7 mean we switch to the n-th stack in the Interrupt Stack Table, contained
- ///< in the TSS if the gate descriptor that contains this field is called.
- };
-} // namespace teachos::arch::context_switching::interrupt_descriptor_table
-
-#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IST_OFFSET_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp b/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp
deleted file mode 100644
index ea8c145..0000000
--- a/arch/x86_64/pre/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp
+++ /dev/null
@@ -1,105 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_SEGMENT_SELECTOR_HPP
-#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_SEGMENT_SELECTOR_HPP
-
-#include <bitset>
-#include <cstdint>
-
-namespace teachos::arch::context_switching::interrupt_descriptor_table
-{
- /**
- * @brief Represents a segment selector in the x86_64 architecture, which points to a valid code segment in the global
- * descriptor table.
- *
- * A segment selector is a 16-bit identifier used to select a segment descriptor
- * from the Global Descriptor Table (GDT) or the Local Descriptor Table (LDT).
- * It contains an index, a table indicator (TI), and a requested privilege level (RPL).
- */
- struct [[gnu::packed]] segment_selector
- {
- /**
- * @brief Possible set bits in our underlying bits and the meaning when they are set.
- */
- enum bitset : uint8_t
- {
- REQUEST_LEVEL_KERNEL =
- 0U << 0U, ///< Highest privileged level used by the kernel to allow for full access of resources.
- REQUEST_LEVEL_ADMIN =
- 1U << 0U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more
- ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended.
- REQUEST_LEVEL_PRIVILEGED_USER =
- 2U << 0U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more
- ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended.
- REQUEST_LEVEL_USER = 3U << 0U, ///< Restricts access to only application and their specific memory.
- LOCAL_DESCRIPTOR_TABLE = 1U << 2U, ///< Wheter the index referes to an entry in the local or global descriptor
- ///< table. If enabled the index points to a local descriptor table, if it is
- ///< cleared it referes to a global descriptor table instead.
- };
-
- /**
- * @brief Default constructor.
- */
- segment_selector() = default;
-
- /**
- * @brief Constructor.
- *
- * @param index Index into the local or global descriptor table. Processor multiplies the index value by 8 (number
- * of bytes in 32-bit segment descriptor) and adds the result to the base GDT or LDT address.
- * @param flags Allows to set flags for the flags field using the unscoped enum contained in this class, used to
- * allow for direct integer conversion.
- */
- constexpr segment_selector(uint16_t index, uint8_t flags)
- : _flags(flags)
- , _index(index)
- {
- // Nothing to do.
- }
-
- /**
- * @brief Checks if the given std::bitset is a subset or equivalent to the underlying data.
- *
- * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng
- * data. Any additional bits that are set are not relevant.
- *
- * @param other Flags that we want to compare against and check if the underlying data has the same bits set.
- * @return Whether the given flags are a subset or equivalent with the underlying data.
- */
- auto contains_flags(std::bitset<3U> other) const -> bool;
-
- /**
- * @brief Gets the index into the global descriptor table or the local descriptor table this segment selector is
- * pointing too.
- *
- * @return Underlying value of the index field, bit 3 - 16.
- */
- [[gnu::section(".user_text")]]
- auto get_index() const -> uint16_t;
-
- /**
- * @brief Defaulted three-way comparsion operator.
- */
- auto operator<=>(segment_selector const & other) const -> std::strong_ordering = default;
-
- /**
- * @brief Combines all bits that are set in the std::bitset flags with the bits already set in the underlying data.
- *
- * @param other Additional bits that should be set.
- */
- auto operator|=(std::bitset<3U> other) -> void;
-
- /**
- * @brief Cast the underlying data into a combined 16-bit form, that contains all data.
- *
- * @return Underlying value combined into it's full size.
- */
- operator uint16_t() const;
-
- private:
- uint8_t _flags : 3 = {}; ///< Underlying bits used to read the flags from.
- uint16_t _index
- : 13 = {}; ///< Index into the local or global descriptor table. Processor multiplies the index value by 16
- ///< (number of bytes in segment descriptor) and adds the result to the base address.
- };
-} // namespace teachos::arch::context_switching::interrupt_descriptor_table
-
-#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_SEGMENT_SELECTOR_HPP
diff --git a/arch/x86_64/pre/include/arch/interrupt_handling/generic_interrupt_handler.hpp b/arch/x86_64/pre/include/arch/interrupt_handling/generic_interrupt_handler.hpp
deleted file mode 100644
index 15b35c1..0000000
--- a/arch/x86_64/pre/include/arch/interrupt_handling/generic_interrupt_handler.hpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_INTERRUPT_HANDLING_GENERIC_INTERRUPT_HANDLER_HPP
-#define TEACHOS_ARCH_X86_64_INTERRUPT_HANDLING_GENERIC_INTERRUPT_HANDLER_HPP
-
-#include <cstdint>
-
-namespace teachos::arch::interrupt_handling
-{
- /**
- * @brief Represents the CPU state during an interrupt.
- *
- * Some interrupts push an error code, while others do not. The full list
- * of which vector number contains the error code can be found here: https://wiki.osdev.org/Exceptions
- */
- struct [[gnu::packed]] interrupt_frame
- {
- // uint64_t error_code; ///< Error code only pushed by some exceptions, therefore it is commented out.
- uint64_t ip; ///< Instruction pointer at the time of the interrupt.
- uint64_t cs; ///< Code segment selector indicating privilege level.
- uint64_t flags; ///< CPU flags (RFLAGS) storing processor state.
- uint64_t sp; ///< Stack pointer at the time of the interrupt.
- uint64_t ss; ///< Stack segment selector, usually unused in 64-bit mode.
- };
-
- /**
- * @brief Generic interrupt handler function.
- *
- * @param frame Pointer to the interrupt frame containing CPU state.
- */
- [[gnu::interrupt]]
- auto generic_interrupt_handler(interrupt_frame * frame) -> void;
-
-} // namespace teachos::arch::interrupt_handling
-
-#endif // TEACHOS_ARCH_X86_64_INTERRUPT_HANDLING_GENERIC_INTERRUPT_HANDLER_HPP
diff --git a/arch/x86_64/pre/include/arch/kernel/cpu/call.hpp b/arch/x86_64/pre/include/arch/kernel/cpu/call.hpp
deleted file mode 100644
index 3c43304..0000000
--- a/arch/x86_64/pre/include/arch/kernel/cpu/call.hpp
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_JMP_HPP
-#define TEACHOS_ARCH_X86_64_KERNEL_CPU_JMP_HPP
-
-#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp"
-
-#include <cstdint>
-
-namespace teachos::arch::kernel::cpu
-{
- /**
- * @brief Far Pointer. Address to function located in another code segment.
- */
- struct far_pointer
- {
- void (*function)(); ///< Address of the function we want to call. (0-63)
- context_switching::interrupt_descriptor_table::segment_selector
- selector; ///< Segment selector pointing to the GDT entry we want to load into register CS. (64-79)
- };
-
- /**
- * @brief Far call - A call to an instruction located in a different segment than the current code segment but at the
- * same privilege level.
- *
- * @param pointer 64-bit operand size far pointer that we want to call.
- */
- auto call(far_pointer pointer) -> void;
-
-} // namespace teachos::arch::kernel::cpu
-
-#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_JMP_HPP
diff --git a/arch/x86_64/pre/include/arch/kernel/cpu/idtr.hpp b/arch/x86_64/pre/include/arch/kernel/cpu/idtr.hpp
deleted file mode 100644
index cb800d0..0000000
--- a/arch/x86_64/pre/include/arch/kernel/cpu/idtr.hpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_IDTR_HPP
-#define TEACHOS_ARCH_X86_64_KERNEL_CPU_IDTR_HPP
-
-#include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp"
-
-#include <bitset>
-#include <cstdint>
-
-namespace teachos::arch::kernel::cpu
-{
- /**
- * @brief Returns the value in the IDTR register.
- *
- * @return Value of IDTR register.
- */
- auto store_interrupt_descriptor_table()
- -> context_switching::interrupt_descriptor_table::interrupt_descriptor_table_pointer;
-
- /**
- * @brief Loads the interrupt_descriptor_table_pointer into the interrupt descriptor table register (IDTR).
- */
- auto load_interrupt_descriptor_table(
- context_switching::interrupt_descriptor_table::interrupt_descriptor_table_pointer const & idt_pointer) -> void;
-
-} // namespace teachos::arch::kernel::cpu
-
-#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_IDTR_HPP
diff --git a/arch/x86_64/pre/include/arch/kernel/cpu/if.hpp b/arch/x86_64/pre/include/arch/kernel/cpu/if.hpp
deleted file mode 100644
index 48707dc..0000000
--- a/arch/x86_64/pre/include/arch/kernel/cpu/if.hpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_IF_HPP
-#define TEACHOS_ARCH_X86_64_KERNEL_CPU_IF_HPP
-
-namespace teachos::arch::kernel::cpu
-{
- /**
- * @brief Sets the interrupt flag (IF) in the EFLAGS register.
- * This allows the processor to respond to maskable hardware interrupts.
- */
- auto set_interrupt_flag() -> void;
-
- /**
- * @brief Clears the interrupt flag (IF) in the EFLAGS register.
- * This will stop the processor to respond to maskable hardware interrupts and needs to be done before changing the
- * Interrupt Descriptor Table with lidt.
- */
- auto clear_interrupt_flag() -> void;
-
-} // namespace teachos::arch::kernel::cpu
-
-#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_IF_HPP
diff --git a/arch/x86_64/pre/include/arch/kernel/cpu/msr.hpp b/arch/x86_64/pre/include/arch/kernel/cpu/msr.hpp
deleted file mode 100644
index 99d6378..0000000
--- a/arch/x86_64/pre/include/arch/kernel/cpu/msr.hpp
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_NXE_HPP
-#define TEACHOS_ARCH_X86_64_KERNEL_CPU_NXE_HPP
-
-#include <bitset>
-#include <cstdint>
-
-namespace teachos::arch::kernel::cpu
-{
- /**
- * @brief Important flags that can be writen into the Extended Feature Enable Register (EFER).
- *
- * @note EFER is a model-specific register allowing to configure CPU extensions. Only the most important extensions
- * are listed below, the rest are excluded for brevity. See https://en.wikipedia.org/wiki/Control_register#EFER for
- * more information.
- */
- enum class efer_flags : uint64_t
- {
- SCE = 1UL << 0UL, ///< System Call Extensions.
- LME = 1UL << 8UL, ///< Long Mode Enabled.
- LMA = 1UL << 10UL, ///< Long Mode Active.
- NXE = 1UL << 11UL, ///< No-Execute Enable.
- SVME = 1UL << 12UL, ///< Secure Virtual Machine Enable.
- LMSLE = 1UL << 13UL, ///< Long Mode Segment Limit Enable.
- FFXSR = 1UL << 14UL, ///< Fast FXSAVE/FXSTOR.
- TCE = 1UL << 15UL, ///< Translation Cache Extension.
- };
-
- /**
- * @brief Reads a 64-bit from the Model-Specific Register (MSR).
- *
- * @note This function reads the value of an MSR specified by the given address. It combines the lower and upper
- * 32-bits of the MSR value read using the 'rdmsr' instruction and returns it as a 64-bit unsigned integer.
- *
- * @param msr The address of the MSR to read.
- * @return The 64-bit value read from the MSR.
- */
- auto read_msr(uint32_t msr) -> uint64_t;
-
- /**
- * @brief Writes a 64-bit value to a Model-Specific Register (MSR).
- *
- * @note This function writes a 64-bit value to the MSR specified by the given address.
- * It splits the 64-bit value into two 32-bit parts and writes them using the
- * `wrmsr` instruction.
- *
- * @param msr The address of the MSR to write to.
- * @param new_value The 64-bit value to write to the MSR.
- */
- auto write_msr(uint32_t msr, uint64_t new_value) -> void;
-
- /**
- * @brief Sets a specific bit in the Extended Feature Enable Register (EFER), which is a Model-Specific Register
- * (MSR).
- *
- * @note This function reads the current value of the EFER register, ORs the specified
- * bit with the current value, and writes the updated value back to the EFER register.
- *
- * @param flag The flag to set in the EFER register.
- */
- auto set_efer_bit(efer_flags flag) -> void;
-
-} // namespace teachos::arch::kernel::cpu
-
-#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_NXE_HPP \ No newline at end of file
diff --git a/arch/x86_64/pre/include/arch/kernel/cpu/tr.hpp b/arch/x86_64/pre/include/arch/kernel/cpu/tr.hpp
deleted file mode 100644
index 7c856f1..0000000
--- a/arch/x86_64/pre/include/arch/kernel/cpu/tr.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_TR_HPP
-#define TEACHOS_ARCH_X86_64_KERNEL_CPU_TR_HPP
-
-#include <bitset>
-#include <cstdint>
-
-namespace teachos::arch::kernel::cpu
-{
-
- /**
- * @brief Returns the value in the LTR register.
- *
- * @return Value of LTR register.
- */
- auto store_task_register() -> uint16_t;
-
- /**
- * @brief Loads the gdt offset to the tss segment descriptor into the task register (TR).
- */
- auto load_task_register(uint16_t gdt_offset) -> void;
-
-} // namespace teachos::arch::kernel::cpu
-
-#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_TR_HPP
diff --git a/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/gate_descriptor.cpp b/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/gate_descriptor.cpp
deleted file mode 100644
index 28f289c..0000000
--- a/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/gate_descriptor.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp"
-
-namespace teachos::arch::context_switching::interrupt_descriptor_table
-{
- gate_descriptor::gate_descriptor(uint128_t flags)
- : _offset_1(flags)
- , _selector(flags >> 19U, flags >> 16U)
- , _ist(flags >> 32U)
- , _flags(flags >> 40U)
- , _offset_2(flags >> 48U)
- {
- // Nothing to do.
- }
-
- gate_descriptor::gate_descriptor(segment_selector selector, ist_offset ist, idt_flags flags, uint64_t offset)
- : _offset_1(offset)
- , _selector(selector)
- , _ist(ist)
- , _flags(flags)
- , _offset_2(offset >> 16U)
- {
- // Nothing to do.
- }
-} // namespace teachos::arch::context_switching::interrupt_descriptor_table
diff --git a/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/idt_flags.cpp b/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/idt_flags.cpp
deleted file mode 100644
index f3b9d5e..0000000
--- a/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/idt_flags.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "arch/context_switching/interrupt_descriptor_table/idt_flags.hpp"
-
-namespace teachos::arch::context_switching::interrupt_descriptor_table
-{
- idt_flags::idt_flags(uint8_t flags)
- : _flags(flags)
- {
- // Nothing to do.
- }
-
- auto idt_flags::contains_flags(std::bitset<8U> other) const -> bool
- {
- return (std::bitset<8U>{_flags} & other) == other;
- }
-
- auto idt_flags::operator|=(std::bitset<8U> other) -> void
- {
- _flags |= other.to_ulong();
- }
-} // namespace teachos::arch::context_switching::interrupt_descriptor_table
diff --git a/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp b/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp
deleted file mode 100644
index 8640385..0000000
--- a/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-#include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp"
-
-#include "arch/exception_handling/assert.hpp"
-#include "arch/interrupt_handling/generic_interrupt_handler.hpp"
-#include "arch/kernel/cpu/idtr.hpp"
-
-namespace teachos::arch::context_switching::interrupt_descriptor_table
-{
- namespace
- {
- /// @brief Amount of currently reserved interrupt indicies.
- /// See https://wiki.osdev.org/Interrupt_Descriptor_Table#IDT_items for more information.
- constexpr uint16_t RESERVED_INTERRUPT_COUNT = 256U;
-
- auto create_interrupt_descriptor_table() -> interrupt_descriptor_table
- {
- interrupt_descriptor_table interrupt_descriptor_table{RESERVED_INTERRUPT_COUNT};
-
- uint64_t offset = reinterpret_cast<uint64_t>(interrupt_handling::generic_interrupt_handler);
- segment_selector selector{1U, segment_selector::REQUEST_LEVEL_KERNEL};
- ist_offset ist{0U};
- idt_flags flags{idt_flags::DESCRIPTOR_LEVEL_KERNEL | idt_flags::INTERRUPT_GATE | idt_flags::PRESENT};
-
- for (std::size_t i = 0; i < interrupt_descriptor_table.size(); i++)
- {
- interrupt_descriptor_table.at(i) = {selector, ist, flags, offset};
- }
-
- return interrupt_descriptor_table;
- }
- } // namespace
-
- auto get_or_create_interrupt_descriptor_table() -> interrupt_descriptor_table &
- {
- // Interrupt Descriptor Table needs to be kept alive
- interrupt_descriptor_table static idt = create_interrupt_descriptor_table();
- return idt;
- }
-
- auto update_interrupt_descriptor_table_register() -> void
- {
- decltype(auto) idt = get_or_create_interrupt_descriptor_table();
-
- interrupt_descriptor_table_pointer idt_pointer{static_cast<uint16_t>((idt.size() * sizeof(gate_descriptor)) - 1),
- idt.data()};
- kernel::cpu::load_interrupt_descriptor_table(idt_pointer);
-
- auto const stored_gdt_pointer = kernel::cpu::store_interrupt_descriptor_table();
- arch::exception_handling::assert(
- idt_pointer == stored_gdt_pointer,
- "[Interrupt Descriptor Table] Loaded IDTR value is not the same as the stored value.");
- }
-} // namespace teachos::arch::context_switching::interrupt_descriptor_table
diff --git a/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.cpp b/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.cpp
deleted file mode 100644
index 7bcbae6..0000000
--- a/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp"
-
-namespace teachos::arch::context_switching::interrupt_descriptor_table
-{
- interrupt_descriptor_table_pointer::interrupt_descriptor_table_pointer(uint16_t table_length,
- gate_descriptor * address)
- : table_length(table_length)
- , address(address)
- {
- // Nothing to do.
- }
-
-} // namespace teachos::arch::context_switching::interrupt_descriptor_table
diff --git a/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/ist_offset.cpp b/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/ist_offset.cpp
deleted file mode 100644
index a70e75d..0000000
--- a/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/ist_offset.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#include "arch/context_switching/interrupt_descriptor_table/ist_offset.hpp"
-
-namespace teachos::arch::context_switching::interrupt_descriptor_table
-{
- ist_offset::ist_offset(uint8_t index)
- : _ist(index)
- {
- // Nothing to do.
- }
-} // namespace teachos::arch::context_switching::interrupt_descriptor_table
diff --git a/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/segment_selector.cpp b/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/segment_selector.cpp
deleted file mode 100644
index 25ba859..0000000
--- a/arch/x86_64/pre/src/context_switching/interrupt_descriptor_table/segment_selector.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp"
-
-namespace teachos::arch::context_switching::interrupt_descriptor_table
-{
- auto segment_selector::contains_flags(std::bitset<3U> other) const -> bool
- {
- return (std::bitset<3U>{_flags} & other) == other;
- }
-
- auto segment_selector::get_index() const -> uint16_t
- {
- return _index;
- }
-
- auto segment_selector::operator|=(std::bitset<3U> other) -> void
- {
- _flags |= other.to_ulong();
- }
-
- segment_selector::operator uint16_t() const
- {
- return *reinterpret_cast<uint16_t const *>(this);
- }
-} // namespace teachos::arch::context_switching::interrupt_descriptor_table
diff --git a/arch/x86_64/pre/src/interrupt_handling/generic_interrupt_handler.cpp b/arch/x86_64/pre/src/interrupt_handling/generic_interrupt_handler.cpp
deleted file mode 100644
index 9d061a8..0000000
--- a/arch/x86_64/pre/src/interrupt_handling/generic_interrupt_handler.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "arch/interrupt_handling/generic_interrupt_handler.hpp"
-
-#include "arch/video/vga/text.hpp"
-
-namespace teachos::arch::interrupt_handling
-{
- auto generic_interrupt_handler(interrupt_frame * frame) -> void
- {
- (void)frame;
- video::vga::text::write("An Interrupt occurred.", video::vga::text::common_attributes::green_on_black);
- video::vga::text::newline();
- }
-} // namespace teachos::arch::interrupt_handling
diff --git a/arch/x86_64/pre/src/kernel/cpu/call.cpp b/arch/x86_64/pre/src/kernel/cpu/call.cpp
deleted file mode 100644
index 98fa248..0000000
--- a/arch/x86_64/pre/src/kernel/cpu/call.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "arch/kernel/cpu/call.hpp"
-
-namespace teachos::arch::kernel::cpu
-{
- auto call(far_pointer pointer) -> void
- {
- asm volatile("rex64 lcall *%[input]" : /* no output from call */ : [input] "m"(pointer));
- }
-} // namespace teachos::arch::kernel::cpu
diff --git a/arch/x86_64/pre/src/kernel/cpu/idtr.cpp b/arch/x86_64/pre/src/kernel/cpu/idtr.cpp
deleted file mode 100644
index 7aa20c1..0000000
--- a/arch/x86_64/pre/src/kernel/cpu/idtr.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#include "arch/kernel/cpu/idtr.hpp"
-
-namespace teachos::arch::kernel::cpu
-{
- auto store_interrupt_descriptor_table()
- -> context_switching::interrupt_descriptor_table::interrupt_descriptor_table_pointer
- {
- context_switching::interrupt_descriptor_table::interrupt_descriptor_table_pointer current_value{};
- asm("sidt %[output]" : [output] "=m"(current_value));
- return current_value;
- }
-
- auto load_interrupt_descriptor_table(
- context_switching::interrupt_descriptor_table::interrupt_descriptor_table_pointer const & idt_pointer) -> void
- {
- asm volatile("lidt %[input]" : /* no output from call */ : [input] "m"(idt_pointer));
- }
-} // namespace teachos::arch::kernel::cpu
diff --git a/arch/x86_64/pre/src/kernel/cpu/if.cpp b/arch/x86_64/pre/src/kernel/cpu/if.cpp
deleted file mode 100644
index 5d056fc..0000000
--- a/arch/x86_64/pre/src/kernel/cpu/if.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace teachos::arch::kernel::cpu
-{
- auto set_interrupt_flag() -> void
- {
- asm volatile("sti");
- }
-
- auto clear_interrupt_flag() -> void
- {
- asm volatile("cli");
- }
-
-} // namespace teachos::arch::kernel::cpu
diff --git a/arch/x86_64/pre/src/kernel/cpu/tr.cpp b/arch/x86_64/pre/src/kernel/cpu/tr.cpp
deleted file mode 100644
index a435540..0000000
--- a/arch/x86_64/pre/src/kernel/cpu/tr.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#include "arch/kernel/cpu/tr.hpp"
-
-namespace teachos::arch::kernel::cpu
-{
- auto store_task_register() -> uint16_t
- {
- uint16_t current_value{};
- asm("str %[output]" : [output] "=r"(current_value));
- return current_value;
- }
-
- auto load_task_register(uint16_t gdt_offset) -> void
- {
- asm volatile("ltr %[input]" : /* no output from call */ : [input] "m"(gdt_offset));
- }
-} // namespace teachos::arch::kernel::cpu
diff --git a/arch/x86_64/src/cpu/interrupts.cpp b/arch/x86_64/src/cpu/interrupts.cpp
index 048c461..907f289 100644
--- a/arch/x86_64/src/cpu/interrupts.cpp
+++ b/arch/x86_64/src/cpu/interrupts.cpp
@@ -1,6 +1,8 @@
#include "arch/cpu/interrupts.hpp"
#include "kapi/cpu.hpp"
+#include "kapi/interrupts.hpp"
+#include "kapi/memory.hpp"
#include "arch/cpu/legacy_pic.hpp"
#include "arch/cpu/segment_selector.hpp"
@@ -14,38 +16,113 @@ namespace arch::cpu
namespace
{
- constexpr auto isr_number_page_fault = 0x0e;
- constexpr auto isr_number_legacy_start = 0x20;
- constexpr auto isr_number_legacy_end = 0x29;
- constexpr auto isr_number_cascade_start = 0x2c;
- constexpr auto isr_number_cascade_end = 0x2f;
+ enum struct exception
+ {
+ divide_error,
+ debug_exception,
+ non_maskable_interrupt,
+ breakpoint,
+ overflow,
+ bound_range_exceeded,
+ invalid_opcode,
+ device_not_available,
+ double_fault,
+ coprocessor_segment_overrun,
+ invalid_tss,
+ segment_not_present,
+ stack_segment_fault,
+ general_protection_fault,
+ page_fault,
+ x87_fpu_floating_point_error = 16,
+ alignment_check,
+ machine_check,
+ simd_floating_point_error,
+ virtualization_exception,
+ control_protection_exception,
+ hypervisor_injection_exception = 28,
+ vmm_communication_exception,
+ security_exception,
+ };
+
+ constexpr auto number_of_exception_vectors = 32u;
+
+ constexpr auto pic_master_irq_start = 0x20;
+ constexpr auto pic_master_irq_end = pic_master_irq_start + 8;
+ constexpr auto pic_slave_irq_start = pic_master_irq_end;
+
+ constexpr auto to_exception_type(exception e)
+ {
+ switch (e)
+ {
+ case exception::divide_error:
+ case exception::x87_fpu_floating_point_error:
+ case exception::simd_floating_point_error:
+ return kapi::cpu::exception::type::arithmetic_error;
+ case exception::breakpoint:
+ return kapi::cpu::exception::type::breakpoint;
+ case exception::invalid_opcode:
+ return kapi::cpu::exception::type::illegal_instruction;
+ case exception::stack_segment_fault:
+ return kapi::cpu::exception::type::memory_access_fault;
+ case exception::general_protection_fault:
+ return kapi::cpu::exception::type::privilege_violation;
+ case exception::page_fault:
+ return kapi::cpu::exception::type::page_fault;
+ case exception::alignment_check:
+ return kapi::cpu::exception::type::alignment_fault;
+ default:
+ return kapi::cpu::exception::type::unknown;
+ }
+ }
- auto handle_page_fault(interrupt_frame * frame) -> void
+ constexpr auto has_error_code(exception e)
{
- auto fault_address = std::uintptr_t{};
- asm volatile("mov %%cr2, %0" : "=r"(fault_address));
-
- auto const present = (frame->interrupt.error_code & 0x1) != 0;
- auto const write = (frame->interrupt.error_code & 0x2) != 0;
- auto const user = (frame->interrupt.error_code & 0x4) != 0;
-
- kstd::println(kstd::print_sink::stderr, "[x86_64:MMU] PAGE FAULT!");
- kstd::println(kstd::print_sink::stderr, "\tFault address: {:#018x}", fault_address);
- kstd::println(kstd::print_sink::stderr, "\tPresent: {}", present);
- kstd::println(kstd::print_sink::stderr, "\tWrite: {}", write);
- kstd::println(kstd::print_sink::stderr, "\tUser: {}", user);
- kstd::println(kstd::print_sink::stderr, "\tRIP: {:#018x}", frame->cpu_saved.rip);
- kstd::println(kstd::print_sink::stderr, "\tHalting the system now!");
-
- kapi::cpu::halt();
+ switch (e)
+ {
+ case exception::double_fault:
+ case exception::invalid_tss:
+ case exception::segment_not_present:
+ case exception::stack_segment_fault:
+ case exception::general_protection_fault:
+ case exception::page_fault:
+ case exception::alignment_check:
+ case exception::control_protection_exception:
+ case exception::security_exception:
+ return true;
+ default:
+ return false;
+ }
}
- auto handle_legacy_interrupt(interrupt_frame * frame) -> void
+ auto dispatch_exception(interrupt_frame * frame) -> bool
{
- kstd::println("[x86_64:SYS] Ignoring 8259 legacy interrupt {:#04x}", frame->interrupt.number);
+ auto type = to_exception_type(static_cast<exception>(frame->interrupt.number));
+ auto fault_address = kapi::memory::linear_address{};
+ auto instruction_pointer = frame->cpu_saved.rip;
+
+ switch (type)
+ {
+ case kapi::cpu::exception::type::page_fault:
+ {
+ asm volatile("mov %%cr2, %0" : "=r"(fault_address));
+ auto present = (frame->interrupt.error_code & 0x1) != 0;
+ auto write = (frame->interrupt.error_code & 0x2) != 0;
+ auto user = (frame->interrupt.error_code & 0x4) != 0;
+
+ return kapi::cpu::dispatch({type, instruction_pointer, fault_address, present, write, user});
+ }
+ default:
+ return kapi::cpu::dispatch({type, instruction_pointer});
+ }
+ }
+ auto acknowledge_pic_interrupt(interrupt_frame * frame) -> void
+ {
+ if (frame->interrupt.number >= pic_slave_irq_start)
+ {
+ pic_slave_control_port::write(pic_end_of_interrupt);
+ }
pic_master_control_port::write(pic_end_of_interrupt);
- pic_slave_control_port::write(pic_end_of_interrupt);
}
} // namespace
@@ -55,22 +132,34 @@ namespace arch::cpu
auto interrupt_dispatch(interrupt_frame * frame) -> void
{
- if ((frame->interrupt.number >= isr_number_legacy_start && frame->interrupt.number <= isr_number_legacy_end) ||
- (frame->interrupt.number >= isr_number_cascade_start && frame->interrupt.number <= isr_number_cascade_end))
+ auto [number, code] = frame->interrupt;
+
+ if (number < number_of_exception_vectors)
{
- handle_legacy_interrupt(frame);
- return;
+ if (!dispatch_exception(frame))
+ {
+ if (has_error_code(static_cast<exception>(number)))
+ {
+ kstd::println(kstd::print_sink::stderr,
+ "[x86_64:CPU] Unhandled exception number {:#04x} received with code {:#04x}", number, code);
+ }
+ else
+ {
+ kstd::println(kstd::print_sink::stderr, "[x86_64:CPU] Unhandled exception number {:#04x} received", number);
+ }
+ }
}
-
- switch (frame->interrupt.number)
+ else
{
- case isr_number_page_fault:
- handle_page_fault(frame);
- break;
- default:
- kstd::println(kstd::print_sink::stderr, "[x86_64:SYS] Unhandled interrupt {:#04x} received with code {:#04x}",
- frame->interrupt.number, frame->interrupt.error_code);
- kapi::cpu::halt();
+ auto irq_number = number - number_of_exception_vectors;
+
+ if (kapi::interrupts::dispatch(irq_number) == kapi::interrupts::status::unhandled)
+ {
+ kstd::println(kstd::print_sink::stderr, "[x86_64:CPU] Unhandled interrupt {:#04x} (IRQ{})", number,
+ irq_number);
+ }
+
+ acknowledge_pic_interrupt(frame);
}
}
}
@@ -83,7 +172,7 @@ namespace arch::cpu
.offset_low = static_cast<std::uint16_t>(isr_stub_table[i] & 0xffff), // NOLINT(readability-magic-numbers)
.m_code_segment = segment_selector{0, false, 1},
.interrupt_stack_table_selector = 0,
- .gate_type = gate_type::interrupt_gate,
+ .gate_type = (i < 32 && i != 2) ? gate_type::trap_gate : gate_type::interrupt_gate,
.descriptor_privilege_level = 0,
.present = true,
.offset_middle =
@@ -111,14 +200,4 @@ namespace arch::cpu
return idtr;
}
- auto enable_interrupts() -> void
- {
- asm volatile("sti");
- }
-
- auto disable_interrupts() -> void
- {
- asm volatile("cli");
- }
-
} // namespace arch::cpu \ No newline at end of file