aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/CMakeLists.txt77
-rw-r--r--arch/x86_64/arch/boot/boot.hpp (renamed from arch/x86_64/include/arch/boot/boot.hpp)2
-rw-r--r--arch/x86_64/arch/boot/boot32.S (renamed from arch/x86_64/src/boot/boot32.S)2
-rw-r--r--arch/x86_64/arch/boot/entry64.s (renamed from arch/x86_64/src/boot/entry64.s)0
-rw-r--r--arch/x86_64/arch/boot/initialize_runtime.cpp (renamed from arch/x86_64/src/boot/initialize_runtime.cpp)0
-rw-r--r--arch/x86_64/arch/boot/ld.hpp (renamed from arch/x86_64/include/arch/boot/ld.hpp)0
-rw-r--r--arch/x86_64/arch/boot/multiboot.s (renamed from arch/x86_64/src/boot/multiboot.s)7
-rw-r--r--arch/x86_64/arch/bus/isa.cpp14
-rw-r--r--arch/x86_64/arch/bus/isa.hpp18
-rw-r--r--arch/x86_64/arch/cpu/control_register.hpp (renamed from arch/x86_64/include/arch/cpu/control_register.hpp)4
-rw-r--r--arch/x86_64/arch/cpu/global_descriptor_table.hpp (renamed from arch/x86_64/include/arch/cpu/global_descriptor_table.hpp)4
-rw-r--r--arch/x86_64/arch/cpu/initialization.cpp164
-rw-r--r--arch/x86_64/arch/cpu/initialization.hpp12
-rw-r--r--arch/x86_64/arch/cpu/interrupts.S112
-rw-r--r--arch/x86_64/arch/cpu/interrupts.cpp203
-rw-r--r--arch/x86_64/arch/cpu/interrupts.hpp (renamed from arch/x86_64/include/arch/cpu/interrupts.hpp)61
-rw-r--r--arch/x86_64/arch/cpu/legacy_pic.hpp19
-rw-r--r--arch/x86_64/arch/cpu/model_specific_register.hpp (renamed from arch/x86_64/include/arch/cpu/model_specific_register.hpp)2
-rw-r--r--arch/x86_64/arch/cpu/registers.hpp (renamed from arch/x86_64/include/arch/cpu/registers.hpp)6
-rw-r--r--arch/x86_64/arch/cpu/segment_descriptor.hpp (renamed from arch/x86_64/include/arch/cpu/segment_descriptor.hpp)0
-rw-r--r--arch/x86_64/arch/cpu/segment_selector.hpp (renamed from arch/x86_64/include/arch/cpu/segment_selector.hpp)0
-rw-r--r--arch/x86_64/arch/cpu/task_state_segment.hpp (renamed from arch/x86_64/include/arch/cpu/task_state_segment.hpp)0
-rw-r--r--arch/x86_64/arch/debug/qemu_output.cpp (renamed from arch/x86_64/src/debug/qemu_output.cpp)4
-rw-r--r--arch/x86_64/arch/debug/qemu_output.hpp (renamed from arch/x86_64/include/arch/debug/qemu_output.hpp)4
-rw-r--r--arch/x86_64/arch/device_io/port_io.hpp (renamed from arch/x86_64/include/arch/device_io/port_io.hpp)11
-rw-r--r--arch/x86_64/arch/devices/init.cpp76
-rw-r--r--arch/x86_64/arch/devices/init.hpp12
-rw-r--r--arch/x86_64/arch/devices/legacy_pit.cpp60
-rw-r--r--arch/x86_64/arch/devices/legacy_pit.hpp29
-rw-r--r--arch/x86_64/arch/devices/local_apic.cpp134
-rw-r--r--arch/x86_64/arch/devices/local_apic.hpp37
-rw-r--r--arch/x86_64/arch/memory/higher_half_mapper.cpp (renamed from arch/x86_64/src/memory/higher_half_mapper.cpp)10
-rw-r--r--arch/x86_64/arch/memory/higher_half_mapper.hpp (renamed from arch/x86_64/include/arch/memory/higher_half_mapper.hpp)4
-rw-r--r--arch/x86_64/arch/memory/kernel_mapper.cpp (renamed from arch/x86_64/src/memory/kernel_mapper.cpp)22
-rw-r--r--arch/x86_64/arch/memory/kernel_mapper.hpp (renamed from arch/x86_64/include/arch/memory/kernel_mapper.hpp)3
-rw-r--r--arch/x86_64/arch/memory/mmu.cpp (renamed from arch/x86_64/src/memory/mmu.cpp)6
-rw-r--r--arch/x86_64/arch/memory/mmu.hpp (renamed from arch/x86_64/include/arch/memory/mmu.hpp)2
-rw-r--r--arch/x86_64/arch/memory/page_table.cpp (renamed from arch/x86_64/src/memory/page_table.cpp)4
-rw-r--r--arch/x86_64/arch/memory/page_table.hpp (renamed from arch/x86_64/include/arch/memory/page_table.hpp)11
-rw-r--r--arch/x86_64/arch/memory/page_utilities.hpp (renamed from arch/x86_64/include/arch/memory/page_utilities.hpp)2
-rw-r--r--arch/x86_64/arch/memory/region_allocator.cpp (renamed from arch/x86_64/src/memory/region_allocator.cpp)49
-rw-r--r--arch/x86_64/arch/memory/region_allocator.hpp (renamed from arch/x86_64/include/arch/memory/region_allocator.hpp)12
-rw-r--r--arch/x86_64/arch/vga/crtc.hpp (renamed from arch/x86_64/include/arch/vga/crtc.hpp)2
-rw-r--r--arch/x86_64/arch/vga/text.hpp10
-rw-r--r--arch/x86_64/arch/vga/text/attribute.hpp (renamed from arch/x86_64/include/arch/vga/text/attribute.hpp)6
-rw-r--r--arch/x86_64/arch/vga/text/buffer.cpp (renamed from arch/x86_64/src/vga/text/buffer.cpp)4
-rw-r--r--arch/x86_64/arch/vga/text/buffer.hpp (renamed from arch/x86_64/include/arch/vga/text/buffer.hpp)4
-rw-r--r--arch/x86_64/arch/vga/text/color.hpp (renamed from arch/x86_64/include/arch/vga/text/color.hpp)2
-rw-r--r--arch/x86_64/arch/vga/text/common_attributes.hpp (renamed from arch/x86_64/include/arch/vga/text/common_attributes.hpp)8
-rw-r--r--arch/x86_64/arch/vga/text/device.cpp (renamed from arch/x86_64/src/vga/text/device.cpp)10
-rw-r--r--arch/x86_64/arch/vga/text/device.hpp (renamed from arch/x86_64/include/arch/vga/text/device.hpp)6
-rw-r--r--arch/x86_64/arch/vga/text/flags.hpp (renamed from arch/x86_64/include/arch/vga/text/flags.hpp)2
-rw-r--r--arch/x86_64/include/arch/vga/text.hpp10
-rw-r--r--arch/x86_64/kapi/boot_modules.cpp53
-rw-r--r--arch/x86_64/kapi/cio.cpp6
-rw-r--r--arch/x86_64/kapi/cpu.cpp80
-rw-r--r--arch/x86_64/kapi/devices.cpp14
-rw-r--r--arch/x86_64/kapi/interrupts.cpp16
-rw-r--r--arch/x86_64/kapi/memory.cpp67
-rw-r--r--arch/x86_64/kapi/system.cpp118
-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/context_switching/main.hpp51
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/syscall/main.hpp91
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/syscall/syscall_enable.hpp18
-rw-r--r--arch/x86_64/pre/include/arch/context_switching/syscall/syscall_handler.hpp18
-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/include/arch/kernel/halt.hpp13
-rw-r--r--arch/x86_64/pre/include/arch/kernel/main.hpp13
-rw-r--r--arch/x86_64/pre/include/arch/user/main.hpp16
-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/context_switching/main.cpp66
-rw-r--r--arch/x86_64/pre/src/context_switching/syscall/main.cpp35
-rw-r--r--arch/x86_64/pre/src/context_switching/syscall/syscall_enable.cpp32
-rw-r--r--arch/x86_64/pre/src/context_switching/syscall/syscall_handler.cpp121
-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/pre/src/kernel/main.cpp71
-rw-r--r--arch/x86_64/pre/src/user/main.cpp35
-rw-r--r--arch/x86_64/scripts/kernel.ld6
-rw-r--r--arch/x86_64/support/grub.cfg.in3
-rw-r--r--arch/x86_64/support/modules/README.md130
-rw-r--r--arch/x86_64/support/modules/ext2_1KB_fs.img3
-rw-r--r--arch/x86_64/support/modules/ext2_2KB_fs.img3
-rw-r--r--arch/x86_64/support/modules/ext2_4KB_fs.img3
102 files changed, 1511 insertions, 1611 deletions
diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt
index 41932c9..20a48f9 100644
--- a/arch/x86_64/CMakeLists.txt
+++ b/arch/x86_64/CMakeLists.txt
@@ -1,44 +1,69 @@
+#[============================================================================[
+# Library
+#]============================================================================]
+
add_library("x86_64" OBJECT)
-add_library("os::arch" ALIAS "x86_64")
+add_library("arch::lib" ALIAS "x86_64")
target_include_directories("x86_64" PUBLIC
- "include"
+ "${CMAKE_CURRENT_SOURCE_DIR}"
)
target_link_libraries("x86_64" PUBLIC
- "os::kapi"
- "libs::multiboot2"
+ "kapi::lib"
+ "multiboot2::lib"
)
target_sources("x86_64" PRIVATE
- # Platform-dependent KAPI implementation
+ "kapi/boot_modules.cpp"
"kapi/cio.cpp"
"kapi/cpu.cpp"
+ "kapi/devices.cpp"
+ "kapi/interrupts.cpp"
"kapi/memory.cpp"
"kapi/system.cpp"
+)
+
+target_sources("x86_64" PRIVATE
+ # CPU Initialization
+ "arch/cpu/initialization.cpp"
+ "arch/cpu/interrupts.cpp"
+ "arch/cpu/interrupts.S"
+
+ # Bus Initialization
+ "arch/bus/isa.cpp"
# Low-level bootstrap
- "src/boot/boot32.S"
- "src/boot/entry64.s"
- "src/boot/initialize_runtime.cpp"
- "src/boot/multiboot.s"
+ "arch/boot/boot32.S"
+ "arch/boot/entry64.s"
+ "arch/boot/initialize_runtime.cpp"
+ "arch/boot/multiboot.s"
# Debug interfaces
- "src/debug/qemu_output.cpp"
+ "arch/debug/qemu_output.cpp"
+
+ # Devices
+ "arch/devices/init.cpp"
+ "arch/devices/legacy_pit.cpp"
+ "arch/devices/local_apic.cpp"
# Memory management
- "src/memory/kernel_mapper.cpp"
- "src/memory/higher_half_mapper.cpp"
- "src/memory/mmu.cpp"
- "src/memory/page_table.cpp"
- "src/memory/region_allocator.cpp"
+ "arch/memory/kernel_mapper.cpp"
+ "arch/memory/higher_half_mapper.cpp"
+ "arch/memory/mmu.cpp"
+ "arch/memory/page_table.cpp"
+ "arch/memory/region_allocator.cpp"
# VGA text mode
- "src/vga/text/buffer.cpp"
- "src/vga/text/device.cpp"
+ "arch/vga/text/buffer.cpp"
+ "arch/vga/text/device.cpp"
)
-file(GLOB_RECURSE ARCH_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "include/**.hpp")
+file(GLOB_RECURSE ARCH_HEADERS
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ CONFIGURE_DEPENDS
+ "include/**.hpp"
+)
target_sources("x86_64" PUBLIC
FILE_SET HEADERS
@@ -46,7 +71,23 @@ target_sources("x86_64" PUBLIC
FILES ${ARCH_HEADERS}
)
+target_include_directories("x86_64" PUBLIC
+ "include"
+)
+
+target_link_libraries("x86_64" PUBLIC
+ "acpi::lib"
+ "elf::lib"
+ "kapi::lib"
+ "kstd::lib"
+ "multiboot2::lib"
+)
+
set(KERNEL_LINKER_SCRIPT
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/kernel.ld"
PARENT_SCOPE
)
+
+set_target_properties("x86_64" PROPERTIES
+ VERIFY_INTERFACE_HEADER_SETS YES
+)
diff --git a/arch/x86_64/include/arch/boot/boot.hpp b/arch/x86_64/arch/boot/boot.hpp
index 3a598f5..7df61c4 100644
--- a/arch/x86_64/include/arch/boot/boot.hpp
+++ b/arch/x86_64/arch/boot/boot.hpp
@@ -31,7 +31,7 @@
// clang-format on
#else
-#include "kapi/boot.hpp" // IWYU pragma: export
+#include <kapi/boot.hpp> // IWYU pragma: export
#include <multiboot2/information.hpp>
diff --git a/arch/x86_64/src/boot/boot32.S b/arch/x86_64/arch/boot/boot32.S
index 1c2fdaf..e6fcd85 100644
--- a/arch/x86_64/src/boot/boot32.S
+++ b/arch/x86_64/arch/boot/boot32.S
@@ -1,4 +1,4 @@
-#include "arch/boot/boot.hpp"
+#include <arch/boot/boot.hpp>
/**
* @brief Uninitialized data for the bootstrapping process.
diff --git a/arch/x86_64/src/boot/entry64.s b/arch/x86_64/arch/boot/entry64.s
index 29fb778..29fb778 100644
--- a/arch/x86_64/src/boot/entry64.s
+++ b/arch/x86_64/arch/boot/entry64.s
diff --git a/arch/x86_64/src/boot/initialize_runtime.cpp b/arch/x86_64/arch/boot/initialize_runtime.cpp
index b08c13c..b08c13c 100644
--- a/arch/x86_64/src/boot/initialize_runtime.cpp
+++ b/arch/x86_64/arch/boot/initialize_runtime.cpp
diff --git a/arch/x86_64/include/arch/boot/ld.hpp b/arch/x86_64/arch/boot/ld.hpp
index 988723d..988723d 100644
--- a/arch/x86_64/include/arch/boot/ld.hpp
+++ b/arch/x86_64/arch/boot/ld.hpp
diff --git a/arch/x86_64/src/boot/multiboot.s b/arch/x86_64/arch/boot/multiboot.s
index 7ccca56..37d8afe 100644
--- a/arch/x86_64/src/boot/multiboot.s
+++ b/arch/x86_64/arch/boot/multiboot.s
@@ -18,6 +18,13 @@ multiboot_header_start:
.long 3
.Lflags_end:
.align 8
+.Linformation_request_start:
+ .word 1
+ .word 0
+ .long .Linformation_request_end - .Linformation_request_start
+ .long 3
+.Linformation_request_end:
+.align 8
.Lend_start:
.word 0
.word 0
diff --git a/arch/x86_64/arch/bus/isa.cpp b/arch/x86_64/arch/bus/isa.cpp
new file mode 100644
index 0000000..f6cc72d
--- /dev/null
+++ b/arch/x86_64/arch/bus/isa.cpp
@@ -0,0 +1,14 @@
+#include <arch/bus/isa.hpp>
+
+#include <kapi/devices.hpp>
+
+#include <cstddef>
+
+namespace arch::bus
+{
+
+ isa::isa(std::size_t major)
+ : kapi::devices::bus{major, 0, "isa"}
+ {}
+
+} // namespace arch::bus \ No newline at end of file
diff --git a/arch/x86_64/arch/bus/isa.hpp b/arch/x86_64/arch/bus/isa.hpp
new file mode 100644
index 0000000..e56f56a
--- /dev/null
+++ b/arch/x86_64/arch/bus/isa.hpp
@@ -0,0 +1,18 @@
+#ifndef TEACHOS_X86_64_BUS_ISA_HPP
+#define TEACHOS_X86_64_BUS_ISA_HPP
+
+#include <kapi/devices/bus.hpp>
+
+#include <cstddef>
+
+namespace arch::bus
+{
+
+ struct isa final : public kapi::devices::bus
+ {
+ isa(std::size_t major);
+ };
+
+} // namespace arch::bus
+
+#endif // TEACHOS_X86_64_BUS_ISA_HPP
diff --git a/arch/x86_64/include/arch/cpu/control_register.hpp b/arch/x86_64/arch/cpu/control_register.hpp
index fafbfc7..9cedc35 100644
--- a/arch/x86_64/include/arch/cpu/control_register.hpp
+++ b/arch/x86_64/arch/cpu/control_register.hpp
@@ -1,9 +1,9 @@
#ifndef TEACHOS_X86_64_CPU_CONTROL_REGISTERS_HPP
#define TEACHOS_X86_64_CPU_CONTROL_REGISTERS_HPP
-// IWYU pragma: private, include "arch/cpu/registers.hpp"
+// IWYU pragma: private, include <arch/cpu/registers.hpp>
-#include "kapi/memory.hpp"
+#include <kapi/memory.hpp>
#include <kstd/ext/bitfield_enum>
diff --git a/arch/x86_64/include/arch/cpu/global_descriptor_table.hpp b/arch/x86_64/arch/cpu/global_descriptor_table.hpp
index 402c87d..b17c509 100644
--- a/arch/x86_64/include/arch/cpu/global_descriptor_table.hpp
+++ b/arch/x86_64/arch/cpu/global_descriptor_table.hpp
@@ -1,9 +1,9 @@
#ifndef TEACHOS_X86_64_GLOBAL_DESCRIPTOR_TABLE_HPP
#define TEACHOS_X86_64_GLOBAL_DESCRIPTOR_TABLE_HPP
-#include "kapi/memory.hpp"
+#include <arch/cpu/segment_descriptor.hpp>
-#include "arch/cpu/segment_descriptor.hpp"
+#include <kapi/memory.hpp>
#include <algorithm>
#include <array>
diff --git a/arch/x86_64/arch/cpu/initialization.cpp b/arch/x86_64/arch/cpu/initialization.cpp
new file mode 100644
index 0000000..1be9c82
--- /dev/null
+++ b/arch/x86_64/arch/cpu/initialization.cpp
@@ -0,0 +1,164 @@
+#include <arch/cpu/initialization.hpp>
+
+#include <arch/cpu/global_descriptor_table.hpp>
+#include <arch/cpu/interrupts.hpp>
+#include <arch/cpu/legacy_pic.hpp>
+#include <arch/cpu/segment_descriptor.hpp>
+#include <arch/cpu/task_state_segment.hpp>
+
+#include <kstd/print>
+
+#include <bit>
+#include <cstdint>
+
+namespace arch::cpu
+{
+
+ namespace
+ {
+ constexpr auto gdt_null_descriptor = segment_descriptor{};
+
+ constexpr auto gdt_kernel_code_descriptor = segment_descriptor{
+ .limit_low = 0xffff,
+ .base_low = 0,
+ .accessed = false,
+ .read_write = false,
+ .direction_or_conforming = false,
+ .executable = true,
+ .type = segment_type::code_or_data,
+ .privilege_level = 0,
+ .present = true,
+ .limit_high = 0xf,
+ .long_mode = true,
+ .protected_mode = false,
+ .granularity = segment_granularity::page,
+ .base_high = 0,
+ };
+
+ constexpr auto gdt_kernel_data_descriptor = segment_descriptor{
+ .limit_low = 0xffff,
+ .base_low = 0,
+ .accessed = false,
+ .read_write = true,
+ .direction_or_conforming = false,
+ .executable = false,
+ .type = segment_type::code_or_data,
+ .privilege_level = 0,
+ .present = true,
+ .limit_high = 0xf,
+ .long_mode = false,
+ .protected_mode = true,
+ .granularity = segment_granularity::page,
+ .base_high = 0,
+ };
+
+ constexpr auto gdt_user_code_descriptor = segment_descriptor{
+ .limit_low = 0xffff,
+ .base_low = 0,
+ .accessed = false,
+ .read_write = false,
+ .direction_or_conforming = false,
+ .executable = true,
+ .type = segment_type::code_or_data,
+ .privilege_level = 3,
+ .present = true,
+ .limit_high = 0xf,
+ .long_mode = true,
+ .protected_mode = false,
+ .granularity = segment_granularity::page,
+ .base_high = 0,
+ };
+
+ constexpr auto gdt_user_data_descriptor = segment_descriptor{
+ .limit_low = 0xffff,
+ .base_low = 0,
+ .accessed = false,
+ .read_write = true,
+ .direction_or_conforming = false,
+ .executable = false,
+ .type = segment_type::code_or_data,
+ .privilege_level = 3,
+ .present = true,
+ .limit_high = 0xf,
+ .long_mode = false,
+ .protected_mode = false,
+ .granularity = segment_granularity::page,
+ .base_high = 0,
+ };
+
+ constexpr auto make_tss_descriptor(task_state_segment const * tss_ptr) -> system_segment_descriptor
+ {
+ auto const address = std::bit_cast<std::uintptr_t>(tss_ptr);
+ auto const limit = sizeof(task_state_segment) - 1;
+
+ return system_segment_descriptor{
+ {
+ .limit_low = limit & 0xffff, // NOLINT(readability-magic-numbers)
+ .base_low = address & 0xffffff, // NOLINT(readability-magic-numbers)
+ .accessed = false,
+ .read_write = false,
+ .direction_or_conforming = false,
+ .executable = false,
+ .type = segment_type::system,
+ .privilege_level = 0,
+ .present = true,
+ .limit_high = (limit >> 16) & 0xf, // NOLINT(readability-magic-numbers)
+ .long_mode = false,
+ .protected_mode = false,
+ .granularity = segment_granularity::byte,
+ .base_high = (address >> 24) & 0xff, // NOLINT(readability-magic-numbers)
+ },
+ (address >> 32) & 0xffff'ffff, // NOLINT(readability-magic-numbers)
+ };
+ }
+ } // namespace
+
+ auto initialize_descriptors() -> void
+ {
+ auto static tss = task_state_segment{};
+ auto static tss_descriptor = make_tss_descriptor(&tss);
+
+ auto static gdt = global_descriptor_table{
+ gdt_null_descriptor, gdt_kernel_code_descriptor, gdt_kernel_data_descriptor,
+ gdt_user_code_descriptor, gdt_user_data_descriptor, tss_descriptor,
+ };
+
+ kstd::println("[x86_64:SYS] Reloading Global Descriptor Table.");
+ gdt.load(1, 2);
+
+ kstd::println("[x86_64:SYS] Initializing Interrupt Descriptor Table.");
+ auto static idt = interrupt_descriptor_table{};
+ idt.load();
+ }
+
+ auto initialize_legacy_interrupts() -> void
+ {
+ constexpr auto pic_init_command = std::uint8_t{0x11};
+ constexpr auto pic_master_offset = std::uint8_t{0x20};
+ constexpr auto pic_slave_offset = std::uint8_t{0x28};
+ constexpr auto pic_cascade_address = std::uint8_t{0x04};
+ constexpr auto pic_cascade_slave_identity = std::uint8_t{0x02};
+ constexpr auto pic_use_8086_mode = std::uint8_t{0x01};
+ constexpr auto pic_master_mask = std::uint8_t{0x00};
+ constexpr auto pic_slave_mask = std::uint8_t{0x00};
+
+ pic_master_control_port::write(pic_init_command);
+ pic_slave_control_port::write(pic_init_command);
+
+ pic_master_data_port::write(pic_master_offset);
+ pic_slave_data_port::write(pic_slave_offset);
+
+ pic_master_data_port::write(pic_cascade_address);
+ pic_slave_data_port::write(pic_cascade_slave_identity);
+
+ pic_master_data_port::write(pic_use_8086_mode);
+ pic_slave_data_port::write(pic_use_8086_mode);
+
+ pic_master_data_port::write(pic_master_mask);
+ pic_slave_data_port::write(pic_slave_mask);
+
+ pic_master_data_port::write(pic_master_mask);
+ pic_slave_data_port::write(pic_slave_mask);
+ }
+
+} // namespace arch::cpu
diff --git a/arch/x86_64/arch/cpu/initialization.hpp b/arch/x86_64/arch/cpu/initialization.hpp
new file mode 100644
index 0000000..564c544
--- /dev/null
+++ b/arch/x86_64/arch/cpu/initialization.hpp
@@ -0,0 +1,12 @@
+#ifndef TEACHOS_ARCH_X86_64_CPU_INITIALIZATION_HPP
+#define TEACHOS_ARCH_X86_64_CPU_INITIALIZATION_HPP
+
+namespace arch::cpu
+{
+ auto initialize_descriptors() -> void;
+
+ auto initialize_legacy_interrupts() -> void;
+
+} // namespace arch::cpu
+
+#endif
diff --git a/arch/x86_64/arch/cpu/interrupts.S b/arch/x86_64/arch/cpu/interrupts.S
new file mode 100644
index 0000000..e59bdd2
--- /dev/null
+++ b/arch/x86_64/arch/cpu/interrupts.S
@@ -0,0 +1,112 @@
+.altmacro
+
+.macro ISR_WITHOUT_ERROR_CODE vector
+ .global isr\vector
+ isr\vector:
+ pushq $0
+ pushq $\vector
+ jmp common_interrupt_handler
+.endm
+
+.macro ISR_WITH_ERROR_CODE vector
+ .global isr\vector
+ isr\vector:
+ pushq $\vector
+ jmp common_interrupt_handler
+.endm
+
+.macro ISR_TABLE_ENTRY vector
+ .quad isr\vector
+.endm
+
+.section .rodata
+.global isr_stub_table
+.align 16
+
+isr_stub_table:
+.set i, 0
+.rept 256
+ ISR_TABLE_ENTRY %i
+ .set i, i + 1
+.endr
+
+
+.section .text
+
+common_interrupt_handler:
+ push %rax
+ push %rbx
+ push %rcx
+ push %rdx
+ push %rbp
+ push %rsi
+ push %rdi
+ push %r8
+ push %r9
+ push %r10
+ push %r11
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+ mov %rsp, %rdi
+ call interrupt_dispatch
+
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %r11
+ pop %r10
+ pop %r9
+ pop %r8
+ pop %rdi
+ pop %rsi
+ pop %rbp
+ pop %rdx
+ pop %rcx
+ pop %rbx
+ pop %rax
+
+ add $16, %rsp
+ iretq
+
+ISR_WITHOUT_ERROR_CODE 0
+ISR_WITHOUT_ERROR_CODE 1
+ISR_WITHOUT_ERROR_CODE 2
+ISR_WITHOUT_ERROR_CODE 3
+ISR_WITHOUT_ERROR_CODE 4
+ISR_WITHOUT_ERROR_CODE 5
+ISR_WITHOUT_ERROR_CODE 6
+ISR_WITHOUT_ERROR_CODE 7
+ISR_WITH_ERROR_CODE 8
+ISR_WITHOUT_ERROR_CODE 9
+ISR_WITH_ERROR_CODE 10
+ISR_WITH_ERROR_CODE 11
+ISR_WITH_ERROR_CODE 12
+ISR_WITH_ERROR_CODE 13
+ISR_WITH_ERROR_CODE 14
+ISR_WITHOUT_ERROR_CODE 15
+ISR_WITHOUT_ERROR_CODE 16
+ISR_WITH_ERROR_CODE 17
+ISR_WITHOUT_ERROR_CODE 18
+ISR_WITHOUT_ERROR_CODE 19
+ISR_WITHOUT_ERROR_CODE 20
+ISR_WITH_ERROR_CODE 21
+ISR_WITHOUT_ERROR_CODE 22
+ISR_WITHOUT_ERROR_CODE 23
+ISR_WITHOUT_ERROR_CODE 24
+ISR_WITHOUT_ERROR_CODE 25
+ISR_WITHOUT_ERROR_CODE 26
+ISR_WITHOUT_ERROR_CODE 27
+ISR_WITHOUT_ERROR_CODE 28
+ISR_WITH_ERROR_CODE 29
+ISR_WITH_ERROR_CODE 30
+ISR_WITHOUT_ERROR_CODE 31
+
+.set i, 32
+.rept 256 - 32
+ ISR_WITHOUT_ERROR_CODE %i
+ .set i, i + 1
+.endr
diff --git a/arch/x86_64/arch/cpu/interrupts.cpp b/arch/x86_64/arch/cpu/interrupts.cpp
new file mode 100644
index 0000000..f40422f
--- /dev/null
+++ b/arch/x86_64/arch/cpu/interrupts.cpp
@@ -0,0 +1,203 @@
+#include <arch/cpu/interrupts.hpp>
+
+#include <arch/cpu/legacy_pic.hpp>
+#include <arch/cpu/segment_selector.hpp>
+
+#include <kapi/cpu.hpp>
+#include <kapi/interrupts.hpp>
+#include <kapi/memory.hpp>
+
+#include <kstd/print>
+
+#include <cstdint>
+
+namespace arch::cpu
+{
+
+ namespace
+ {
+ 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;
+ }
+ }
+
+ constexpr auto has_error_code(exception e)
+ {
+ 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 dispatch_exception(interrupt_frame * frame) -> bool
+ {
+ 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);
+ }
+ } // namespace
+
+ extern "C"
+ {
+ extern std::uintptr_t const isr_stub_table[256];
+
+ auto interrupt_dispatch(interrupt_frame * frame) -> void
+ {
+ auto [number, code] = frame->interrupt;
+
+ if (number < number_of_exception_vectors)
+ {
+ 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);
+ }
+ }
+ }
+ else
+ {
+ 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);
+ }
+ }
+ }
+
+ interrupt_descriptor_table::interrupt_descriptor_table() noexcept
+ {
+ for (auto i = 0uz; i < 256; ++i)
+ {
+ m_descriptors[i] = gate_descriptor{
+ .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 = (i < 32 && i != 2) ? gate_type::trap_gate : gate_type::interrupt_gate,
+ .descriptor_privilege_level = 0,
+ .present = true,
+ .offset_middle =
+ static_cast<std::uint16_t>((isr_stub_table[i] >> 16) & 0xffff), // NOLINT(readability-magic-numbers)
+ .offset_high =
+ static_cast<std::uint32_t>((isr_stub_table[i] >> 32) & 0xffff'ffff), // NOLINT(readability-magic-numbers)
+ };
+ }
+ }
+
+ auto interrupt_descriptor_table::load() const -> void
+ {
+ interrupt_descriptor_table_register{.limit = sizeof(m_descriptors) - 1, .base = m_descriptors.data()}.load();
+ }
+
+ auto interrupt_descriptor_table_register::load() const -> void
+ {
+ asm volatile("lidt %0" : : "m"(*this));
+ }
+
+ auto interrupt_descriptor_table_register::read() -> interrupt_descriptor_table_register
+ {
+ interrupt_descriptor_table_register idtr{};
+ asm volatile("sidt %0" : : "m"(idtr));
+ return idtr;
+ }
+
+} // namespace arch::cpu \ No newline at end of file
diff --git a/arch/x86_64/include/arch/cpu/interrupts.hpp b/arch/x86_64/arch/cpu/interrupts.hpp
index 92c5824..6162f56 100644
--- a/arch/x86_64/include/arch/cpu/interrupts.hpp
+++ b/arch/x86_64/arch/cpu/interrupts.hpp
@@ -1,7 +1,9 @@
#ifndef TEACHOS_X86_64_CPU_INTERRUPTS_HPP
#define TEACHOS_X86_64_CPU_INTERRUPTS_HPP
-#include "arch/cpu/segment_selector.hpp"
+#include <arch/cpu/segment_selector.hpp>
+
+#include <kapi/memory.hpp>
#include <array>
#include <cstdint>
@@ -30,7 +32,7 @@ namespace arch::cpu
//! Reserved
std::uint8_t : 5;
//! The type of this gate.
- gate_type gate_type : 4;
+ enum gate_type gate_type : 4;
//! Reserved
std::uint8_t : 1;
//! The privilege level required to enter through this gate.
@@ -48,14 +50,67 @@ namespace arch::cpu
static_assert(sizeof(gate_descriptor) == 2 * sizeof(std::uint64_t));
static_assert(std::is_aggregate_v<gate_descriptor>);
+ //! The stack frame as established by the low-level assembly interrupt stubs.
+ //!
+ //! @note The layout of this struct is reverse than what would reasonably be expected. The reason for this reversal is
+ //! that fact that it represents a stack frame. Stack frames on x86_64 grow towards lower addresses, meaning the first
+ //! item on the stack is the last item in C++ memory layout order.
+ struct interrupt_frame
+ {
+ 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{};
+ } handler_saved;
+
+ struct
+ {
+ std::uint64_t number{};
+ std::uint64_t error_code{};
+ } interrupt;
+
+ struct
+ {
+ kapi::memory::linear_address rip{};
+ std::uint64_t cs{};
+ std::uint64_t rflags{};
+ kapi::memory::linear_address rsp{};
+ std::uint64_t ss{};
+ } cpu_saved;
+ };
+
struct interrupt_descriptor_table
{
- interrupt_descriptor_table();
+ interrupt_descriptor_table() noexcept;
+
+ auto load() const -> void;
private:
std::array<gate_descriptor, 256> m_descriptors{};
};
+ struct [[gnu::packed]] interrupt_descriptor_table_register
+ {
+ std::uint16_t limit;
+ gate_descriptor const * base;
+
+ auto load() const -> void;
+ auto static read() -> interrupt_descriptor_table_register;
+ };
+
} // namespace arch::cpu
#endif \ No newline at end of file
diff --git a/arch/x86_64/arch/cpu/legacy_pic.hpp b/arch/x86_64/arch/cpu/legacy_pic.hpp
new file mode 100644
index 0000000..56ca9c4
--- /dev/null
+++ b/arch/x86_64/arch/cpu/legacy_pic.hpp
@@ -0,0 +1,19 @@
+#ifndef TEACHOS_X86_64_CPU_LEGACY_PIC_HPP
+#define TEACHOS_X86_64_CPU_LEGACY_PIC_HPP
+
+#include <arch/device_io/port_io.hpp>
+
+#include <cstdint>
+
+namespace arch::cpu
+{
+ using pic_master_control_port = io::port<0x20, std::uint8_t, io::port_read, io::port_write>;
+ using pic_master_data_port = io::port<0x21, std::uint8_t, io::port_read, io::port_write>;
+ using pic_slave_control_port = io::port<0xa0, std::uint8_t, io::port_read, io::port_write>;
+ using pic_slave_data_port = io::port<0xa1, std::uint8_t, io::port_read, io::port_write>;
+
+ constexpr auto pic_end_of_interrupt = std::uint8_t{0x20};
+
+} // namespace arch::cpu
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/include/arch/cpu/model_specific_register.hpp b/arch/x86_64/arch/cpu/model_specific_register.hpp
index 8539a24..bd4aff9 100644
--- a/arch/x86_64/include/arch/cpu/model_specific_register.hpp
+++ b/arch/x86_64/arch/cpu/model_specific_register.hpp
@@ -1,7 +1,7 @@
#ifndef TEACHOS_X86_64_CPU_MODEL_SPECIFIC_REGISTER_HPP
#define TEACHOS_X86_64_CPU_MODEL_SPECIFIC_REGISTER_HPP
-// IWYU pragma: private, include "x86_64/cpu/registers.hpp"
+// IWYU pragma: private, include <x86_64/cpu/registers.hpp>
#include <kstd/ext/bitfield_enum>
diff --git a/arch/x86_64/include/arch/cpu/registers.hpp b/arch/x86_64/arch/cpu/registers.hpp
index d7def10..58633f6 100644
--- a/arch/x86_64/include/arch/cpu/registers.hpp
+++ b/arch/x86_64/arch/cpu/registers.hpp
@@ -1,10 +1,10 @@
#ifndef TEACHOS_X86_64_CPU_REGISTERS_HPP
#define TEACHOS_X86_64_CPU_REGISTERS_HPP
-#include "kapi/memory.hpp"
+#include <arch/cpu/control_register.hpp> // IWYU pragma: export
+#include <arch/cpu/model_specific_register.hpp> // IWYU pragma: export
-#include "arch/cpu/control_register.hpp" // IWYU pragma: export
-#include "arch/cpu/model_specific_register.hpp" // IWYU pragma: export
+#include <kapi/memory.hpp>
namespace arch::cpu
{
diff --git a/arch/x86_64/include/arch/cpu/segment_descriptor.hpp b/arch/x86_64/arch/cpu/segment_descriptor.hpp
index 9570670..9570670 100644
--- a/arch/x86_64/include/arch/cpu/segment_descriptor.hpp
+++ b/arch/x86_64/arch/cpu/segment_descriptor.hpp
diff --git a/arch/x86_64/include/arch/cpu/segment_selector.hpp b/arch/x86_64/arch/cpu/segment_selector.hpp
index 1a78c47..1a78c47 100644
--- a/arch/x86_64/include/arch/cpu/segment_selector.hpp
+++ b/arch/x86_64/arch/cpu/segment_selector.hpp
diff --git a/arch/x86_64/include/arch/cpu/task_state_segment.hpp b/arch/x86_64/arch/cpu/task_state_segment.hpp
index 57729dd..57729dd 100644
--- a/arch/x86_64/include/arch/cpu/task_state_segment.hpp
+++ b/arch/x86_64/arch/cpu/task_state_segment.hpp
diff --git a/arch/x86_64/src/debug/qemu_output.cpp b/arch/x86_64/arch/debug/qemu_output.cpp
index 535017d..71acede 100644
--- a/arch/x86_64/src/debug/qemu_output.cpp
+++ b/arch/x86_64/arch/debug/qemu_output.cpp
@@ -1,6 +1,6 @@
-#include "arch/debug/qemu_output.hpp"
+#include <arch/debug/qemu_output.hpp>
-#include "kapi/cio.hpp"
+#include <kapi/cio.hpp>
#include <algorithm>
#include <string_view>
diff --git a/arch/x86_64/include/arch/debug/qemu_output.hpp b/arch/x86_64/arch/debug/qemu_output.hpp
index e72eb39..5ddd4be 100644
--- a/arch/x86_64/include/arch/debug/qemu_output.hpp
+++ b/arch/x86_64/arch/debug/qemu_output.hpp
@@ -1,9 +1,9 @@
#ifndef TEACHOS_X86_64_DEBUG_QEMU_OUTPUT_HPP
#define TEACHOS_X86_64_DEBUG_QEMU_OUTPUT_HPP
-#include "kapi/cio.hpp"
+#include <arch/device_io/port_io.hpp>
-#include "arch/device_io/port_io.hpp"
+#include <kapi/cio.hpp>
#include <string_view>
diff --git a/arch/x86_64/include/arch/device_io/port_io.hpp b/arch/x86_64/arch/device_io/port_io.hpp
index 65e58e3..4c8d66a 100644
--- a/arch/x86_64/include/arch/device_io/port_io.hpp
+++ b/arch/x86_64/arch/device_io/port_io.hpp
@@ -69,9 +69,9 @@ namespace arch::io
//! The assembly templates used for writing to an I/O port.
constexpr auto static code = std::array{
- std::string_view{"mov %[port], %%dx\nmov %%dx, %[data]\nout %%al, %%dx"},
- std::string_view{"mov %[port], %%dx\nmov %%dx, %[data]\nout %%ax, %%dx"},
- std::string_view{"mov %[port], %%dx\nmov %%dx, %[data]\nout %%eax, %%dx"},
+ std::string_view{"mov %[port], %%dx\nmov %[data], %%al\nout %%al, %%dx"},
+ std::string_view{"mov %[port], %%dx\nmov %[data], %%ax\nout %%ax, %%dx"},
+ std::string_view{"mov %[port], %%dx\nmov %[data], %%eax\nout %%eax, %%dx"},
};
};
@@ -102,6 +102,11 @@ namespace arch::io
: std::string_view{"eax"};
};
+ auto inline wait() -> void
+ {
+ port<0x80, std::uint8_t, port_write>::write<std::uint8_t>(0);
+ }
+
} // namespace arch::io
#endif \ No newline at end of file
diff --git a/arch/x86_64/arch/devices/init.cpp b/arch/x86_64/arch/devices/init.cpp
new file mode 100644
index 0000000..c30e8cf
--- /dev/null
+++ b/arch/x86_64/arch/devices/init.cpp
@@ -0,0 +1,76 @@
+#include <arch/devices/init.hpp>
+
+#include <arch/boot/boot.hpp>
+#include <arch/bus/isa.hpp>
+#include <arch/devices/legacy_pit.hpp>
+
+#include <kapi/acpi.hpp>
+#include <kapi/cpu.hpp>
+#include <kapi/devices.hpp>
+
+#include <acpi/acpi.hpp>
+
+#include <kstd/memory>
+#include <kstd/print>
+
+#include <cstdint>
+#include <utility>
+
+namespace arch::devices
+{
+
+ namespace
+ {
+ constexpr auto pit_frequency_in_hz = std::uint32_t{100u};
+
+ auto get_acpi_root_pointer() -> kstd::observer_ptr<::acpi::rsdp const>
+ {
+ auto const & mbi = kapi::boot::bootstrap_information.mbi;
+ auto system_description_pointer = static_cast<::acpi::rsdp const *>(nullptr);
+
+ if (auto const & xsdp = mbi->maybe_acpi_xsdp())
+ {
+ auto data = xsdp->pointer().data();
+
+ system_description_pointer = reinterpret_cast<::acpi::xsdp const *>(data);
+ }
+ else if (auto const & rsdp = mbi->maybe_acpi_rsdp())
+ {
+ auto data = rsdp->pointer().data();
+ system_description_pointer = reinterpret_cast<::acpi::rsdp const *>(data);
+ }
+
+ return kstd::make_observer(system_description_pointer);
+ }
+ } // namespace
+
+ auto init_acpi_devices() -> void
+ {
+ auto acpi_root_pointer = get_acpi_root_pointer();
+ if (acpi_root_pointer && acpi_root_pointer->validate())
+ {
+ if (kapi::acpi::init(*acpi_root_pointer))
+ {
+ kstd::println("[x86_64:DEV] ACPI subsystem initialized.");
+ }
+ }
+
+ kapi::cpu::discover_topology();
+ }
+
+ auto init_legacy_devices() -> void
+ {
+ kstd::println("[x86_64:DEV] Initializing ISA bus...");
+
+ auto isa_major_number = kapi::devices::allocate_major_number();
+ auto isa_bus = kstd::make_unique<arch::bus::isa>(isa_major_number);
+
+ auto pit_major_number = kapi::devices::allocate_major_number();
+ auto pit = kstd::make_unique<arch::devices::legacy_pit>(pit_major_number, pit_frequency_in_hz);
+ isa_bus->add_child(std::move(pit));
+
+ auto & root_bus = kapi::devices::get_root_bus();
+ root_bus.add_child(std::move(isa_bus));
+ }
+
+} // namespace arch::devices
diff --git a/arch/x86_64/arch/devices/init.hpp b/arch/x86_64/arch/devices/init.hpp
new file mode 100644
index 0000000..c5fbf37
--- /dev/null
+++ b/arch/x86_64/arch/devices/init.hpp
@@ -0,0 +1,12 @@
+#ifndef TEACHOS_ARCH_X86_64_DEVICES_INIT_HPP
+#define TEACHOS_ARCH_X86_64_DEVICES_INIT_HPP
+
+namespace arch::devices
+{
+
+ auto init_acpi_devices() -> void;
+ auto init_legacy_devices() -> void;
+
+} // namespace arch::devices
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/arch/devices/legacy_pit.cpp b/arch/x86_64/arch/devices/legacy_pit.cpp
new file mode 100644
index 0000000..d542d47
--- /dev/null
+++ b/arch/x86_64/arch/devices/legacy_pit.cpp
@@ -0,0 +1,60 @@
+#include <arch/devices/legacy_pit.hpp>
+
+#include <arch/device_io/port_io.hpp>
+
+#include <kapi/devices.hpp>
+#include <kapi/devices/device.hpp>
+#include <kapi/interrupts.hpp>
+
+#include <cstddef>
+#include <cstdint>
+
+namespace arch::devices
+{
+
+ namespace
+ {
+ using command_port = io::port<0x43, std::uint8_t, io::port_write>;
+ using channel_0_port = io::port<0x40, std::uint8_t, io::port_write>;
+ using channel_1_port = io::port<0x41, std::uint8_t, io::port_write>;
+ using channel_2_port = io::port<0x42, std::uint8_t, io::port_write>;
+
+ constexpr auto base_frequency = 1'193'182u;
+ constexpr auto square_wave_mode = 0x36;
+ } // namespace
+
+ legacy_pit::legacy_pit(std::size_t major, std::uint32_t frequency_in_hz)
+ : kapi::devices::device{major, 0, "legacy_pit"}
+ , m_irq_number{0}
+ , m_frequency_in_hz{frequency_in_hz}
+ {}
+
+ auto legacy_pit::init() -> bool
+ {
+ auto divisor = static_cast<std::uint16_t>(base_frequency / m_frequency_in_hz);
+
+ kapi::interrupts::register_handler(m_irq_number, *this);
+
+ command_port::write<std::uint8_t>(square_wave_mode);
+ io::wait();
+ channel_0_port::write<std::uint8_t>(divisor & 0xff);
+ io::wait();
+ channel_0_port::write<std::uint8_t>(divisor >> 8 & 0xff);
+ io::wait();
+
+ return true;
+ }
+
+ auto legacy_pit::handle_interrupt(std::uint32_t irq_number) -> kapi::interrupts::status
+ {
+ if (irq_number != m_irq_number)
+ {
+ return kapi::interrupts::status::unhandled;
+ }
+
+ ++m_ticks;
+
+ return kapi::interrupts::status::handled;
+ }
+
+} // namespace arch::devices \ No newline at end of file
diff --git a/arch/x86_64/arch/devices/legacy_pit.hpp b/arch/x86_64/arch/devices/legacy_pit.hpp
new file mode 100644
index 0000000..356895c
--- /dev/null
+++ b/arch/x86_64/arch/devices/legacy_pit.hpp
@@ -0,0 +1,29 @@
+#ifndef TEACHOS_ARCH_X86_64_DEVICES_LEGACY_PIT_HPP
+#define TEACHOS_ARCH_X86_64_DEVICES_LEGACY_PIT_HPP
+
+#include <kapi/devices/device.hpp>
+#include <kapi/interrupts.hpp>
+
+#include <cstddef>
+#include <cstdint>
+
+namespace arch::devices
+{
+
+ struct legacy_pit : kapi::devices::device, kapi::interrupts::handler
+ {
+ legacy_pit(std::size_t major, std::uint32_t frequency_in_hz);
+
+ auto init() -> bool override;
+
+ auto handle_interrupt(std::uint32_t irq_number) -> kapi::interrupts::status override;
+
+ private:
+ std::uint32_t m_irq_number{};
+ std::uint32_t m_frequency_in_hz{};
+ std::uint64_t m_ticks{};
+ };
+
+} // namespace arch::devices
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/arch/devices/local_apic.cpp b/arch/x86_64/arch/devices/local_apic.cpp
new file mode 100644
index 0000000..660921b
--- /dev/null
+++ b/arch/x86_64/arch/devices/local_apic.cpp
@@ -0,0 +1,134 @@
+#include <arch/devices/local_apic.hpp>
+
+#include <kapi/devices.hpp>
+#include <kapi/memory.hpp>
+
+#include <kstd/print>
+
+#include <cstddef>
+#include <cstdint>
+#include <utility>
+
+namespace arch::devices
+{
+
+ namespace
+ {
+ constexpr auto lapic_enable_bit = 0x100u;
+ constexpr auto spurious_interrupt_vector = 0xFFu;
+
+ constexpr auto offset_of_version = 0u;
+ constexpr auto offset_of_max_lvt_entry = 16u;
+ constexpr auto offset_of_eoi_suppression = 24u;
+
+ } // namespace
+
+ enum struct local_apic::registers : std::ptrdiff_t
+ {
+ id = 0x020,
+ version = 0x030,
+ task_priority = 0x080,
+ arbitration_priority = 0x090,
+ processor_priority = 0x0a0,
+ eoi = 0x0b0,
+ remote_read = 0x0c0,
+ logical_destination = 0x0d0,
+ destination_format = 0x0e0,
+ spurious_interrupt_vector = 0x0f0,
+ in_service_0 = 0x100,
+ in_service_1 = 0x110,
+ in_service_2 = 0x120,
+ in_service_3 = 0x130,
+ in_service_4 = 0x140,
+ in_service_5 = 0x150,
+ in_service_6 = 0x160,
+ in_service_7 = 0x170,
+ trigger_mode_0 = 0x180,
+ trigger_mode_1 = 0x190,
+ trigger_mode_2 = 0x1a0,
+ trigger_mode_3 = 0x1b0,
+ trigger_mode_4 = 0x1c0,
+ trigger_mode_5 = 0x1d0,
+ trigger_mode_6 = 0x1e0,
+ trigger_mode_7 = 0x1f0,
+ interrupt_request_0 = 0x200,
+ interrupt_request_1 = 0x210,
+ interrupt_request_2 = 0x220,
+ interrupt_request_3 = 0x230,
+ interrupt_request_4 = 0x240,
+ interrupt_request_5 = 0x250,
+ interrupt_request_6 = 0x260,
+ interrupt_request_7 = 0x270,
+ error_status = 0x280,
+ lvt_corrected_machine_check_interrupt = 0x2f0,
+ interrupt_command_0 = 0x300,
+ interrupt_command_1 = 0x310,
+ lvt_timer = 0x320,
+ lvt_thermal_sensors = 0x330,
+ lvt_performance_monitoring_counters = 0x340,
+ lvt_local_interrupt_0 = 0x350,
+ lvt_local_interrupt_1 = 0x360,
+ lvt_error = 0x370,
+ initial_count = 0x380,
+ current_count = 0x390,
+ divide_configuration = 0x3e0,
+ };
+
+ local_apic::local_apic(std::size_t major, std::size_t minor, std::uint64_t hardware_id,
+ kapi::memory::physical_address base, bool is_bsp)
+ : kapi::devices::device{major, minor, "lapic"}
+ , m_hardware_id{hardware_id}
+ , m_base{base}
+ , m_is_bsp{is_bsp}
+ {}
+
+ auto local_apic::init() -> bool
+ {
+ auto static shared_virtual_base = kapi::memory::allocate_mmio_region(1);
+ auto static is_mapped = false;
+
+ if (!is_mapped)
+ {
+ if (!kapi::memory::map_mmio_region(shared_virtual_base, m_base, kapi::memory::page_mapper::flags::writable))
+ {
+ kstd::println("[x86_64:DEV] LAPIC {} MMIO mapping failed!", m_hardware_id);
+ return false;
+ }
+ is_mapped = true;
+ }
+
+ m_mapped_region = shared_virtual_base;
+
+ if (m_is_bsp)
+ {
+ auto raw_version = read_register(registers::version);
+ m_version = (raw_version >> offset_of_version) & 0xff;
+ m_highest_lvt_entry_index = (raw_version >> offset_of_max_lvt_entry) & 0xff;
+ m_supports_eoi_broadcast_suppression = (raw_version >> offset_of_eoi_suppression) & 0x1;
+
+ write_register(registers::spurious_interrupt_vector, lapic_enable_bit | spurious_interrupt_vector);
+
+ kstd::println("[x86_64:DEV] LAPIC initialized. version: {#x} | max_lvt_entry: {} | eoi_suppression: {:s}",
+ m_version, m_highest_lvt_entry_index, m_supports_eoi_broadcast_suppression);
+ }
+ else
+ {
+ kstd::println("[x86_64:DEV] LAPIC {} is not on the BSP, deferring initialization.", m_hardware_id);
+ }
+
+ return true;
+ }
+
+ auto local_apic::read_register(registers id) const -> std::uint32_t
+ {
+ auto reg = static_cast<std::uint32_t volatile *>(m_mapped_region.first + std::to_underlying(id));
+ return *reg;
+ }
+
+ auto local_apic::write_register(registers id, std::uint32_t value) -> void
+ {
+ auto reg = static_cast<std::uint32_t volatile *>(m_mapped_region.first + std::to_underlying(id));
+ *reg = value;
+ }
+
+} // namespace arch::devices
diff --git a/arch/x86_64/arch/devices/local_apic.hpp b/arch/x86_64/arch/devices/local_apic.hpp
new file mode 100644
index 0000000..f8f080d
--- /dev/null
+++ b/arch/x86_64/arch/devices/local_apic.hpp
@@ -0,0 +1,37 @@
+#ifndef TEACHOS_ARCH_X86_64_DEVICES_LOCAL_APIC_HPP
+#define TEACHOS_ARCH_X86_64_DEVICES_LOCAL_APIC_HPP
+
+#include <kapi/devices/device.hpp>
+#include <kapi/memory.hpp>
+
+#include <cstddef>
+#include <cstdint>
+
+namespace arch::devices
+{
+
+ struct local_apic : kapi::devices::device
+ {
+ local_apic(std::size_t major, std::size_t minor, std::uint64_t hardware_id, kapi::memory::physical_address base,
+ bool is_bsp);
+
+ auto init() -> bool override;
+
+ private:
+ enum struct registers : std::ptrdiff_t;
+
+ [[nodiscard]] auto read_register(registers id) const -> std::uint32_t;
+ auto write_register(registers id, std::uint32_t value) -> void;
+
+ std::uint64_t m_hardware_id{};
+ kapi::memory::physical_address m_base{};
+ kapi::memory::mmio_region m_mapped_region{};
+ bool m_is_bsp{};
+ std::uint8_t m_version{};
+ std::uint8_t m_highest_lvt_entry_index{};
+ bool m_supports_eoi_broadcast_suppression{};
+ };
+
+} // namespace arch::devices
+
+#endif
diff --git a/arch/x86_64/src/memory/higher_half_mapper.cpp b/arch/x86_64/arch/memory/higher_half_mapper.cpp
index abb54a3..75adb3c 100644
--- a/arch/x86_64/src/memory/higher_half_mapper.cpp
+++ b/arch/x86_64/arch/memory/higher_half_mapper.cpp
@@ -1,10 +1,10 @@
-#include "arch/memory/higher_half_mapper.hpp"
+#include <arch/memory/higher_half_mapper.hpp>
-#include "kapi/memory.hpp"
-#include "kapi/system.hpp"
+#include <arch/memory/page_table.hpp>
+#include <arch/memory/page_utilities.hpp>
-#include "arch/memory/page_table.hpp"
-#include "arch/memory/page_utilities.hpp"
+#include <kapi/memory.hpp>
+#include <kapi/system.hpp>
#include <algorithm>
#include <array>
diff --git a/arch/x86_64/include/arch/memory/higher_half_mapper.hpp b/arch/x86_64/arch/memory/higher_half_mapper.hpp
index c8df40c..9b02ee6 100644
--- a/arch/x86_64/include/arch/memory/higher_half_mapper.hpp
+++ b/arch/x86_64/arch/memory/higher_half_mapper.hpp
@@ -1,9 +1,9 @@
#ifndef TEACHOS_X86_64_HIGHER_HALF_MAPPER_HPP
#define TEACHOS_X86_64_HIGHER_HALF_MAPPER_HPP
-#include "kapi/memory.hpp"
+#include <arch/memory/page_table.hpp>
-#include "arch/memory/page_table.hpp"
+#include <kapi/memory.hpp>
#include <cstddef>
diff --git a/arch/x86_64/src/memory/kernel_mapper.cpp b/arch/x86_64/arch/memory/kernel_mapper.cpp
index 08c32c5..74272a0 100644
--- a/arch/x86_64/src/memory/kernel_mapper.cpp
+++ b/arch/x86_64/arch/memory/kernel_mapper.cpp
@@ -1,14 +1,16 @@
-#include "arch/memory/kernel_mapper.hpp"
+#include <arch/memory/kernel_mapper.hpp>
-#include "kapi/memory.hpp"
-#include "kapi/system.hpp"
+#include <arch/boot/ld.hpp>
-#include "arch/boot/ld.hpp"
-
-#include <kstd/print>
+#include <kapi/memory.hpp>
+#include <kapi/system.hpp>
#include <elf/format.hpp>
#include <elf/section_header.hpp>
+
+#include <kstd/print>
+#include <kstd/units>
+
#include <multiboot2/information.hpp>
#include <algorithm>
@@ -19,13 +21,14 @@
#include <string_view>
#include <utility>
+using namespace std::string_view_literals;
+using namespace kstd::units_literals;
+
namespace arch::memory
{
namespace
{
- using namespace std::string_view_literals;
-
constexpr auto static ignored_section_prefixes = std::array{
".boot_"sv,
};
@@ -71,7 +74,8 @@ namespace arch::memory
auto kernel_mapper::map_section(section_header_type const & section, std::string_view name,
kapi::memory::page_mapper & mapper) -> void
{
- auto number_of_pages = (section.size + (PLATFORM_PAGE_SIZE - 1)) / PLATFORM_PAGE_SIZE;
+ auto number_of_pages =
+ (kstd::units::bytes{section.size} + (kapi::memory::page::size - 1_B)) / kapi::memory::page::size;
auto linear_start_address = kapi::memory::linear_address{section.virtual_load_address};
auto physical_start_address = kapi::memory::physical_address{section.virtual_load_address & ~m_kernel_load_base};
diff --git a/arch/x86_64/include/arch/memory/kernel_mapper.hpp b/arch/x86_64/arch/memory/kernel_mapper.hpp
index 4329f1b..adbf688 100644
--- a/arch/x86_64/include/arch/memory/kernel_mapper.hpp
+++ b/arch/x86_64/arch/memory/kernel_mapper.hpp
@@ -1,10 +1,11 @@
#ifndef TEACHOS_X86_64_KERNEL_MAPPER_HPP
#define TEACHOS_X86_64_KERNEL_MAPPER_HPP
-#include "kapi/memory.hpp"
+#include <kapi/memory.hpp>
#include <elf/format.hpp>
#include <elf/section_header.hpp>
+
#include <multiboot2/information.hpp>
#include <cstdint>
diff --git a/arch/x86_64/src/memory/mmu.cpp b/arch/x86_64/arch/memory/mmu.cpp
index ea23278..2b53fa4 100644
--- a/arch/x86_64/src/memory/mmu.cpp
+++ b/arch/x86_64/arch/memory/mmu.cpp
@@ -1,8 +1,8 @@
-#include "arch/memory/mmu.hpp"
+#include <arch/memory/mmu.hpp>
-#include "kapi/memory.hpp"
+#include <arch/cpu/registers.hpp>
-#include "arch/cpu/registers.hpp"
+#include <kapi/memory.hpp>
namespace arch::memory
{
diff --git a/arch/x86_64/include/arch/memory/mmu.hpp b/arch/x86_64/arch/memory/mmu.hpp
index 2d64184..64373f4 100644
--- a/arch/x86_64/include/arch/memory/mmu.hpp
+++ b/arch/x86_64/arch/memory/mmu.hpp
@@ -1,7 +1,7 @@
#ifndef TEACHOS_X86_64_MEMORY_MMU_HPP
#define TEACHOS_X86_64_MEMORY_MMU_HPP
-#include "kapi/memory/address.hpp"
+#include <kapi/memory/address.hpp>
namespace arch::memory
{
diff --git a/arch/x86_64/src/memory/page_table.cpp b/arch/x86_64/arch/memory/page_table.cpp
index 26cdd29..2180420 100644
--- a/arch/x86_64/src/memory/page_table.cpp
+++ b/arch/x86_64/arch/memory/page_table.cpp
@@ -1,6 +1,6 @@
-#include "arch/memory/page_table.hpp"
+#include <arch/memory/page_table.hpp>
-#include "kapi/memory.hpp"
+#include <kapi/memory.hpp>
#include <algorithm>
#include <bit>
diff --git a/arch/x86_64/include/arch/memory/page_table.hpp b/arch/x86_64/arch/memory/page_table.hpp
index 2889d38..ce3d3a1 100644
--- a/arch/x86_64/include/arch/memory/page_table.hpp
+++ b/arch/x86_64/arch/memory/page_table.hpp
@@ -1,9 +1,10 @@
#ifndef TEACHOS_X86_64_PAGE_TABLE_HPP
#define TEACHOS_X86_64_PAGE_TABLE_HPP
-#include "kapi/memory.hpp"
+#include <kapi/memory.hpp>
#include <kstd/ext/bitfield_enum>
+#include <kstd/units>
#include <array>
#include <cstddef>
@@ -116,7 +117,7 @@ namespace arch::memory
};
//! The maximum number of entries in this table.
- constexpr auto static entry_count{kapi::memory::page::size / sizeof(entry)};
+ constexpr auto static entry_count{kapi::memory::page::size / kstd::units::bytes{sizeof(entry)}};
//! Get the entry at the given index.
//!
@@ -173,7 +174,7 @@ namespace arch::memory
result |= mapper_flags::writable;
}
- if ((flags & table_flags::disable_cache) != table_flags::empty)
+ if ((flags & (table_flags::disable_cache | table_flags::write_through)) != table_flags::empty)
{
result |= mapper_flags::uncached;
}
@@ -210,7 +211,7 @@ namespace arch::memory
if ((flags & mapper_flags::uncached) != mapper_flags::empty)
{
- result |= table_flags::disable_cache;
+ result |= (table_flags::disable_cache | table_flags::write_through);
}
if ((flags & mapper_flags::supervisor_only) == mapper_flags::empty)
@@ -228,4 +229,4 @@ namespace arch::memory
} // namespace arch::memory
-#endif \ No newline at end of file
+#endif
diff --git a/arch/x86_64/include/arch/memory/page_utilities.hpp b/arch/x86_64/arch/memory/page_utilities.hpp
index c48e74f..068e824 100644
--- a/arch/x86_64/include/arch/memory/page_utilities.hpp
+++ b/arch/x86_64/arch/memory/page_utilities.hpp
@@ -1,7 +1,7 @@
#ifndef TEACHOS_X86_64_PAGE_UTILITIES_HPP
#define TEACHOS_X86_64_PAGE_UTILITIES_HPP
-#include "kapi/memory.hpp"
+#include <kapi/memory.hpp>
#include <cstddef>
diff --git a/arch/x86_64/src/memory/region_allocator.cpp b/arch/x86_64/arch/memory/region_allocator.cpp
index facb1f2..4086a10 100644
--- a/arch/x86_64/src/memory/region_allocator.cpp
+++ b/arch/x86_64/arch/memory/region_allocator.cpp
@@ -1,7 +1,7 @@
-#include "arch/memory/region_allocator.hpp"
+#include <arch/memory/region_allocator.hpp>
-#include "kapi/memory/address.hpp"
-#include "kapi/memory/frame.hpp"
+#include <kapi/memory/address.hpp>
+#include <kapi/memory/frame.hpp>
#include <multiboot2/information.hpp>
@@ -35,7 +35,7 @@ namespace arch::memory
, m_kernel_end{kapi::memory::frame::containing(mem_info.image_range.second)}
, m_multiboot_start{kapi::memory::frame::containing(mem_info.mbi_range.first)}
, m_multiboot_end{kapi::memory::frame::containing(mem_info.mbi_range.second)}
- // TODO BA-FS26: Protect MB2 boot modules
+ , m_multiboot_information{mem_info.mbi}
{
choose_next_region();
}
@@ -76,19 +76,40 @@ namespace arch::memory
}
}
- if (falls_within(m_next_frame, m_kernel_start, m_kernel_end))
+ auto advanced = true;
+ while (advanced)
{
- m_next_frame = m_kernel_end + 1;
- }
+ advanced = false;
- if (falls_within(m_next_frame, m_multiboot_start, m_multiboot_end))
- {
- m_next_frame = m_multiboot_end + 1;
- }
+ if (falls_within(m_next_frame, m_kernel_start, m_kernel_end))
+ {
+ m_next_frame = m_kernel_end + 1;
+ advanced = true;
+ continue;
+ }
- if (falls_within(m_next_frame, m_kernel_start, m_kernel_end))
- {
- m_next_frame = m_kernel_end + 1;
+ if (falls_within(m_next_frame, m_multiboot_start, m_multiboot_end))
+ {
+ m_next_frame = m_multiboot_end + 1;
+ advanced = true;
+ continue;
+ }
+
+ if (m_multiboot_information)
+ {
+ for (auto const & module : m_multiboot_information->modules())
+ {
+ auto module_start = kapi::memory::frame::containing(kapi::memory::physical_address{module.start_address});
+ auto module_end = kapi::memory::frame::containing(kapi::memory::physical_address{module.end_address});
+
+ if (falls_within(m_next_frame, module_start, module_end))
+ {
+ m_next_frame = module_end + 1;
+ advanced = true;
+ break;
+ }
+ }
+ }
}
if (m_next_frame > last_frame(*m_current_region))
diff --git a/arch/x86_64/include/arch/memory/region_allocator.hpp b/arch/x86_64/arch/memory/region_allocator.hpp
index 1c5885e..5d9da2e 100644
--- a/arch/x86_64/include/arch/memory/region_allocator.hpp
+++ b/arch/x86_64/arch/memory/region_allocator.hpp
@@ -1,9 +1,9 @@
#ifndef TEACHOS_X86_64_MEMORY_REGION_ALLOCATOR_HPP
#define TEACHOS_X86_64_MEMORY_REGION_ALLOCATOR_HPP
-#include "kapi/memory/address.hpp"
-#include "kapi/memory/frame.hpp"
-#include "kapi/memory/frame_allocator.hpp"
+#include <kapi/memory/address.hpp>
+#include <kapi/memory/frame.hpp>
+#include <kapi/memory/frame_allocator.hpp>
#include <multiboot2/information.hpp>
@@ -42,6 +42,11 @@ namespace arch::memory
//! These include available, unavailable, and reclaimable regions. In general, only frames that are located in
//! non-reserved (as in available) regions should be allocated for page storage.
multiboot2::memory_map memory_map;
+
+ //! The loader supplied Multiboot2 information structure.
+ //!
+ //! This is used to query boot module ranges so these frames can be excluded from early allocations.
+ multiboot2::information_view const * mbi;
};
using region = multiboot2::memory_map::region;
@@ -80,6 +85,7 @@ namespace arch::memory
kapi::memory::frame m_kernel_end; //!< The end of the kernel image in physical memory.
kapi::memory::frame m_multiboot_start; //!< The start of the Multiboot2 information in physical memory.
kapi::memory::frame m_multiboot_end; //!< The end of the Multiboot2 information in physical memory.
+ multiboot2::information_view const * m_multiboot_information; //!< Source of Multiboot2 module ranges.
};
} // namespace arch::memory
diff --git a/arch/x86_64/include/arch/vga/crtc.hpp b/arch/x86_64/arch/vga/crtc.hpp
index dbdc365..a8bec93 100644
--- a/arch/x86_64/include/arch/vga/crtc.hpp
+++ b/arch/x86_64/arch/vga/crtc.hpp
@@ -1,7 +1,7 @@
#ifndef TEACHOS_X86_64_VGA_IO_HPP
#define TEACHOS_X86_64_VGA_IO_HPP
-#include "arch/device_io/port_io.hpp"
+#include <arch/device_io/port_io.hpp>
#include <cstddef>
diff --git a/arch/x86_64/arch/vga/text.hpp b/arch/x86_64/arch/vga/text.hpp
new file mode 100644
index 0000000..2e73dd2
--- /dev/null
+++ b/arch/x86_64/arch/vga/text.hpp
@@ -0,0 +1,10 @@
+#ifndef TEACHOS_X86_64_VGA_TEXT_HPP
+#define TEACHOS_X86_64_VGA_TEXT_HPP
+
+#include <arch/vga/text/attribute.hpp> // IWYU pragma: export
+#include <arch/vga/text/color.hpp> // IWYU pragma: export
+#include <arch/vga/text/common_attributes.hpp> // IWYU pragma: export
+#include <arch/vga/text/device.hpp> // IWYU pragma: export
+#include <arch/vga/text/flags.hpp> // IWYU pragma: export
+
+#endif // TEACHOS_ARCH_X86_64_VIDEO_VGA_TEXT_HPP \ No newline at end of file
diff --git a/arch/x86_64/include/arch/vga/text/attribute.hpp b/arch/x86_64/arch/vga/text/attribute.hpp
index 6a0f995..6395aed 100644
--- a/arch/x86_64/include/arch/vga/text/attribute.hpp
+++ b/arch/x86_64/arch/vga/text/attribute.hpp
@@ -1,10 +1,10 @@
#ifndef TEACHOS_X86_64_VGA_TEXT_ATTRIBUTE_HPP
#define TEACHOS_X86_64_VGA_TEXT_ATTRIBUTE_HPP
-// IWYU pragma: private, include "arch/vga/text.hpp"
+// IWYU pragma: private, include <arch/vga/text.hpp>
-#include "arch/vga/text/color.hpp"
-#include "arch/vga/text/flags.hpp"
+#include <arch/vga/text/color.hpp>
+#include <arch/vga/text/flags.hpp>
namespace arch::vga::text
{
diff --git a/arch/x86_64/src/vga/text/buffer.cpp b/arch/x86_64/arch/vga/text/buffer.cpp
index 7112573..498b9a3 100644
--- a/arch/x86_64/src/vga/text/buffer.cpp
+++ b/arch/x86_64/arch/vga/text/buffer.cpp
@@ -1,6 +1,6 @@
-#include "arch/vga/text/buffer.hpp"
+#include <arch/vga/text/buffer.hpp>
-#include "arch/vga/text/attribute.hpp"
+#include <arch/vga/text/attribute.hpp>
#include <algorithm>
#include <bit>
diff --git a/arch/x86_64/include/arch/vga/text/buffer.hpp b/arch/x86_64/arch/vga/text/buffer.hpp
index 648d37a..8eb6645 100644
--- a/arch/x86_64/include/arch/vga/text/buffer.hpp
+++ b/arch/x86_64/arch/vga/text/buffer.hpp
@@ -1,9 +1,9 @@
#ifndef TEACHOS_X86_64_VGA_TEXT_BUFFER_HPP
#define TEACHOS_X86_64_VGA_TEXT_BUFFER_HPP
-// IWYU pragma: private, include "arch/vga/text.hpp"
+// IWYU pragma: private, include <arch/vga/text.hpp>
-#include "arch/vga/text/attribute.hpp"
+#include <arch/vga/text/attribute.hpp>
#include <cstddef>
#include <span>
diff --git a/arch/x86_64/include/arch/vga/text/color.hpp b/arch/x86_64/arch/vga/text/color.hpp
index a541830..e0ad6df 100644
--- a/arch/x86_64/include/arch/vga/text/color.hpp
+++ b/arch/x86_64/arch/vga/text/color.hpp
@@ -1,7 +1,7 @@
#ifndef TEACHOS_X86_64_VGA_TEXT_COLOR_HPP
#define TEACHOS_X86_64_VGA_TEXT_COLOR_HPP
-// IWYU pragma: private, include "arch/vga/text.hpp"
+// IWYU pragma: private, include <arch/vga/text.hpp>
#include <cstdint>
diff --git a/arch/x86_64/include/arch/vga/text/common_attributes.hpp b/arch/x86_64/arch/vga/text/common_attributes.hpp
index 9bd61a5..3d8929f 100644
--- a/arch/x86_64/include/arch/vga/text/common_attributes.hpp
+++ b/arch/x86_64/arch/vga/text/common_attributes.hpp
@@ -1,11 +1,11 @@
#ifndef TEACHOS_X86_64_VGA_TEXT_COMMON_ATTRIBUTES_HPP
#define TEACHOS_X86_64_VGA_TEXT_COMMON_ATTRIBUTES_HPP
-// IWYU pragma: private, include "arch/vga/text.hpp"
+// IWYU pragma: private, include <arch/vga/text.hpp>
-#include "arch/vga/text/attribute.hpp"
-#include "arch/vga/text/color.hpp"
-#include "arch/vga/text/flags.hpp"
+#include <arch/vga/text/attribute.hpp>
+#include <arch/vga/text/color.hpp>
+#include <arch/vga/text/flags.hpp>
namespace arch::vga::text
{
diff --git a/arch/x86_64/src/vga/text/device.cpp b/arch/x86_64/arch/vga/text/device.cpp
index dcacd8c..8468358 100644
--- a/arch/x86_64/src/vga/text/device.cpp
+++ b/arch/x86_64/arch/vga/text/device.cpp
@@ -1,9 +1,9 @@
-#include "kapi/cio.hpp"
+#include <arch/boot/boot.hpp>
+#include <arch/boot/ld.hpp>
+#include <arch/vga/crtc.hpp>
+#include <arch/vga/text.hpp>
-#include "arch/boot/boot.hpp"
-#include "arch/boot/ld.hpp"
-#include "arch/vga/crtc.hpp"
-#include "arch/vga/text.hpp"
+#include <kapi/cio.hpp>
#include <bit>
#include <cstddef>
diff --git a/arch/x86_64/include/arch/vga/text/device.hpp b/arch/x86_64/arch/vga/text/device.hpp
index 11b3281..0a0e017 100644
--- a/arch/x86_64/include/arch/vga/text/device.hpp
+++ b/arch/x86_64/arch/vga/text/device.hpp
@@ -1,11 +1,11 @@
#ifndef TEACHOS_X86_64_VGA_TEXT_DEVICE_HPP
#define TEACHOS_X86_64_VGA_TEXT_DEVICE_HPP
-// IWYU pragma: private, include "arch/vga/text.hpp"
+// IWYU pragma: private, include <arch/vga/text.hpp>
-#include "kapi/cio.hpp"
+#include <arch/vga/text/buffer.hpp>
-#include "arch/vga/text/buffer.hpp"
+#include <kapi/cio.hpp>
#include <string_view>
diff --git a/arch/x86_64/include/arch/vga/text/flags.hpp b/arch/x86_64/arch/vga/text/flags.hpp
index 67c6c11..7a29e33 100644
--- a/arch/x86_64/include/arch/vga/text/flags.hpp
+++ b/arch/x86_64/arch/vga/text/flags.hpp
@@ -1,7 +1,7 @@
#ifndef TEACHOS_X86_64_VGA_TEXT_FLAGS_HPP
#define TEACHOS_X86_64_VGA_TEXT_FLAGS_HPP
-// IWYU pragma: private, include "arch/vga/text.hpp"
+// IWYU pragma: private, include <arch/vga/text.hpp>
namespace arch::vga::text
{
diff --git a/arch/x86_64/include/arch/vga/text.hpp b/arch/x86_64/include/arch/vga/text.hpp
deleted file mode 100644
index f81ab60..0000000
--- a/arch/x86_64/include/arch/vga/text.hpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef TEACHOS_X86_64_VGA_TEXT_HPP
-#define TEACHOS_X86_64_VGA_TEXT_HPP
-
-#include "text/attribute.hpp" // IWYU pragma: export
-#include "text/color.hpp" // IWYU pragma: export
-#include "text/common_attributes.hpp" // IWYU pragma: export
-#include "text/device.hpp" // IWYU pragma: export
-#include "text/flags.hpp" // IWYU pragma: export
-
-#endif // TEACHOS_ARCH_X86_64_VIDEO_VGA_TEXT_HPP \ No newline at end of file
diff --git a/arch/x86_64/kapi/boot_modules.cpp b/arch/x86_64/kapi/boot_modules.cpp
new file mode 100644
index 0000000..fb6bf46
--- /dev/null
+++ b/arch/x86_64/kapi/boot_modules.cpp
@@ -0,0 +1,53 @@
+#include <kapi/boot_modules.hpp>
+
+#include <arch/boot/boot.hpp>
+#include <arch/boot/ld.hpp>
+
+#include <kapi/boot.hpp>
+#include <kapi/boot_module/boot_module.hpp>
+#include <kapi/boot_module/boot_module_registry.hpp>
+#include <kapi/memory.hpp>
+#include <kapi/system.hpp>
+
+#include <kstd/print>
+
+#include <multiboot2/information.hpp>
+
+#include <algorithm>
+#include <atomic>
+#include <bit>
+#include <cstdint>
+#include <optional>
+
+namespace kapi::boot_modules
+{
+ namespace
+ {
+ auto constinit registry = std::optional<kapi::boot_modules::boot_module_registry>{};
+ } // namespace
+
+ auto init() -> void
+ {
+ auto static constinit is_initialized = std::atomic_flag{};
+ if (is_initialized.test_and_set())
+ {
+ system::panic("[x86_64] Boot module registry has already been initialized.");
+ }
+
+ kstd::println("[x86_64:BOOT_MODULES] Initializing boot module registry.");
+
+ registry.emplace(kapi::boot_modules::boot_module_registry{});
+
+ auto modules = boot::bootstrap_information.mbi->modules();
+ std::ranges::for_each(modules, [](auto const & module) {
+ registry->add_boot_module(kapi::boot_modules::boot_module{
+ .name = module.string(),
+ .start_address =
+ memory::linear_address{module.start_address + std::bit_cast<std::uintptr_t>(&arch::boot::TEACHOS_VMA)},
+ .size = module.end_address - module.start_address,
+ });
+ });
+
+ set_boot_module_registry(*registry);
+ }
+} // namespace kapi::boot_modules \ No newline at end of file
diff --git a/arch/x86_64/kapi/cio.cpp b/arch/x86_64/kapi/cio.cpp
index 015cf5e..b33c6e0 100644
--- a/arch/x86_64/kapi/cio.cpp
+++ b/arch/x86_64/kapi/cio.cpp
@@ -1,7 +1,7 @@
-#include "kapi/cio.hpp"
+#include <kapi/cio.hpp>
-#include "arch/debug/qemu_output.hpp"
-#include "arch/vga/text.hpp"
+#include <arch/debug/qemu_output.hpp>
+#include <arch/vga/text.hpp>
#include <optional>
diff --git a/arch/x86_64/kapi/cpu.cpp b/arch/x86_64/kapi/cpu.cpp
index 2a0f8f7..40dc228 100644
--- a/arch/x86_64/kapi/cpu.cpp
+++ b/arch/x86_64/kapi/cpu.cpp
@@ -1,12 +1,90 @@
-#include "kapi/cpu.hpp"
+#include <kapi/cpu.hpp>
+
+#include <arch/cpu/initialization.hpp>
+#include <arch/devices/local_apic.hpp>
+
+#include <kapi/acpi.hpp>
+#include <kapi/devices.hpp>
+#include <kapi/devices/cpu.hpp>
+#include <kapi/memory.hpp>
+#include <kapi/system.hpp>
+
+#include <acpi/acpi.hpp>
+
+#include <kstd/memory>
+#include <kstd/print>
+
+#include <atomic>
+#include <ranges>
+#include <utility>
namespace kapi::cpu
{
+ namespace
+ {
+ constexpr auto candidate_flags = ::acpi::processor_local_apic_entry::flags::processor_enabled //
+ | ::acpi::processor_local_apic_entry::flags::online_capable;
+ }
+
+ 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");
__builtin_unreachable();
}
+ auto discover_topology() -> bool
+ {
+ auto static const cpu_major = kapi::devices::allocate_major_number();
+ auto static const core_major = kapi::devices::allocate_major_number();
+ auto static const interrupt_controller_major = kapi::devices::allocate_major_number();
+
+ auto madt = kapi::acpi::get_table<::acpi::table_signature_v<::acpi::madt>>();
+ if (!madt)
+ {
+ kstd::println("[x86_64:PLT] Failed to find ACPI APIC table");
+ return false;
+ }
+
+ auto lapic_entries = *madt | std::views::filter([](auto const & entry) {
+ return entry.type() == ::acpi::madt_entry::type::processor_local_apic;
+ }) | std::views::transform([](auto const & entry) {
+ return static_cast<::acpi::processor_local_apic_entry const &>(entry);
+ }) | std::views::filter([](auto const & entry) { return static_cast<bool>(entry.flags() & candidate_flags); });
+
+ auto bsp_found = false;
+ auto core_count = 0uz;
+ auto local_apic_address = memory::physical_address{madt->local_interrupt_controller_address()};
+ auto cpu_bus = kstd::make_unique<devices::cpu>(cpu_major, 0);
+
+ for (auto const & apic : lapic_entries)
+ {
+ auto is_bsp = !bsp_found;
+ bsp_found = true;
+ auto core = kstd::make_unique<devices::cpu::core>(core_major, core_count, apic.processor_id(), is_bsp);
+ core->add_child(kstd::make_unique<arch::devices::local_apic>(interrupt_controller_major, core_count, apic.id(),
+ local_apic_address, is_bsp));
+ cpu_bus->add_child(std::move(core));
+ ++core_count;
+ }
+
+ devices::get_root_bus().add_child(std::move(cpu_bus));
+
+ kstd::println("[x86_64:PLT] Found {} CPU cores", core_count);
+ return core_count > 0;
+ }
+
} // namespace kapi::cpu
diff --git a/arch/x86_64/kapi/devices.cpp b/arch/x86_64/kapi/devices.cpp
new file mode 100644
index 0000000..f188c92
--- /dev/null
+++ b/arch/x86_64/kapi/devices.cpp
@@ -0,0 +1,14 @@
+#include <kapi/devices.hpp>
+
+#include <arch/devices/init.hpp>
+
+namespace kapi::devices
+{
+
+ auto init_platform_devices() -> void
+ {
+ arch::devices::init_acpi_devices();
+ arch::devices::init_legacy_devices();
+ }
+
+} // namespace kapi::devices \ 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..85acc0f
--- /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/memory.cpp b/arch/x86_64/kapi/memory.cpp
index a9e1216..5b870d5 100644
--- a/arch/x86_64/kapi/memory.cpp
+++ b/arch/x86_64/kapi/memory.cpp
@@ -1,18 +1,19 @@
-#include "kapi/memory.hpp"
+#include <kapi/memory.hpp>
-#include "kapi/boot.hpp"
-#include "kapi/system.hpp"
+#include <arch/boot/boot.hpp>
+#include <arch/boot/ld.hpp>
+#include <arch/cpu/registers.hpp>
+#include <arch/memory/higher_half_mapper.hpp>
+#include <arch/memory/kernel_mapper.hpp>
+#include <arch/memory/page_table.hpp>
+#include <arch/memory/page_utilities.hpp>
+#include <arch/memory/region_allocator.hpp>
-#include "arch/boot/boot.hpp"
-#include "arch/boot/ld.hpp"
-#include "arch/cpu/registers.hpp"
-#include "arch/memory/higher_half_mapper.hpp"
-#include "arch/memory/kernel_mapper.hpp"
-#include "arch/memory/page_table.hpp"
-#include "arch/memory/page_utilities.hpp"
-#include "arch/memory/region_allocator.hpp"
+#include <kapi/boot.hpp>
+#include <kapi/system.hpp>
#include <kstd/print>
+#include <kstd/units>
#include <multiboot2/constants.hpp>
#include <multiboot2/information.hpp>
@@ -28,6 +29,8 @@
#include <span>
#include <utility>
+using namespace kstd::units_literals;
+
namespace kapi::memory
{
@@ -46,13 +49,14 @@ namespace kapi::memory
}
auto const & mbi = boot::bootstrap_information.mbi;
- auto mbi_span = std::span{std::bit_cast<std::byte *>(mbi), mbi->size_bytes()};
+ auto mbi_span = std::span{std::bit_cast<std::byte *>(mbi), static_cast<std::size_t>(mbi->size())};
auto image_span = std::span{&arch::boot::_start_physical, &arch::boot::_end_physical};
return arch::memory::region_allocator::memory_information{
.image_range = std::make_pair(physical_address{&image_span.front()}, physical_address{&image_span.back()}),
.mbi_range = std::make_pair(physical_address{&mbi_span.front()}, physical_address{&mbi_span.back()}),
.memory_map = *memory_map,
+ .mbi = mbi,
};
}
@@ -106,10 +110,10 @@ namespace kapi::memory
[[maybe_unused]] auto remap_multiboot_information(page_mapper & mapper) -> void
{
auto mbi_base = std::bit_cast<std::uintptr_t>(boot::bootstrap_information.mbi);
- auto mbi_size = boot::bootstrap_information.mbi->size_bytes();
+ auto mbi_size = boot::bootstrap_information.mbi->size();
auto mbi_physical_start = physical_address{mbi_base & ~std::bit_cast<std::uintptr_t>(&arch::boot::TEACHOS_VMA)};
auto mbi_virtual_start = linear_address{mbi_base};
- auto mbi_block_count = (mbi_size + PLATFORM_FRAME_SIZE - 1) / PLATFORM_FRAME_SIZE;
+ auto mbi_block_count = (mbi_size + frame::size - 1_B) / frame::size;
for (auto i = 0uz; i < mbi_block_count; ++i)
{
@@ -119,6 +123,24 @@ namespace kapi::memory
}
}
+ [[maybe_unused]] auto remap_bootloader_modules(page_mapper & mapper) -> void
+ {
+ std::ranges::for_each(boot::bootstrap_information.mbi->modules(), [&mapper](auto const & module) {
+ auto module_physical_start = physical_address{module.start_address};
+ auto module_virtual_start =
+ linear_address{module.start_address + std::bit_cast<std::uintptr_t>(&arch::boot::TEACHOS_VMA)};
+ auto module_size = static_cast<kstd::units::bytes>(module.end_address - module.start_address);
+ auto module_block_count = (module_size + frame::size - 1_B) / frame::size;
+
+ for (auto i = 0uz; i < module_block_count; ++i)
+ {
+ auto page = page::containing(module_virtual_start) + i;
+ auto frame = frame::containing(module_physical_start) + i;
+ mapper.map(page, frame, page_mapper::flags::writable | page_mapper::flags::supervisor_only);
+ }
+ });
+ }
+
[[maybe_unused]] auto handoff_to_kernel_pmm(frame_allocator & new_allocator) -> void
{
auto memory_map = boot::bootstrap_information.mbi->memory_map();
@@ -128,7 +150,7 @@ namespace kapi::memory
}))
{
auto start = frame::containing(physical_address{region.base});
- auto count = region.size_in_B / page::size;
+ auto count = kstd::units::bytes{region.size_in_B} / page::size;
new_allocator.release_many({start, count});
}
@@ -148,14 +170,22 @@ namespace kapi::memory
[&](auto frame) { new_allocator.mark_used(frame); });
auto mbi_base = std::bit_cast<std::uintptr_t>(boot::bootstrap_information.mbi);
- auto mbi_size = boot::bootstrap_information.mbi->size_bytes();
+ auto mbi_size = boot::bootstrap_information.mbi->size();
auto mbi_address = physical_address{mbi_base & ~std::bit_cast<std::uintptr_t>(&arch::boot::TEACHOS_VMA)};
auto mbi_start = frame::containing(mbi_address);
auto mbi_end = frame::containing(mbi_address + mbi_size) + 1;
- // TODO BA-FS26: Protect MB2 boot modules
-
std::ranges::for_each(std::views::iota(mbi_start, mbi_end), [&](auto frame) { new_allocator.mark_used(frame); });
+
+ std::ranges::for_each(boot::bootstrap_information.mbi->modules(), [&](auto const & module) {
+ auto module_physical_start = physical_address{module.start_address};
+ auto module_size = module.end_address - module.start_address;
+ auto module_start = frame::containing(module_physical_start);
+ auto module_end = frame::containing(module_physical_start + module_size) + 1;
+
+ std::ranges::for_each(std::views::iota(module_start, module_end),
+ [&](auto frame) { new_allocator.mark_used(frame); });
+ });
}
} // namespace
@@ -196,6 +226,7 @@ namespace kapi::memory
remap_kernel(*higher_half_mapper);
remap_vga_text_mode_buffer(*higher_half_mapper);
remap_multiboot_information(*higher_half_mapper);
+ remap_bootloader_modules(*higher_half_mapper);
auto current_cr3 = arch::cpu::cr3::read();
auto old_pml4 = static_cast<arch::memory::page_table *>(current_cr3.address());
diff --git a/arch/x86_64/kapi/system.cpp b/arch/x86_64/kapi/system.cpp
index ca4418e..73a77e5 100644
--- a/arch/x86_64/kapi/system.cpp
+++ b/arch/x86_64/kapi/system.cpp
@@ -1,122 +1,8 @@
-#include "kapi/system.hpp"
-
-#include "arch/cpu/global_descriptor_table.hpp"
-#include "arch/cpu/segment_descriptor.hpp"
-#include "arch/cpu/task_state_segment.hpp"
-
-#include <kstd/print>
-
-#include <bit>
-#include <cstdint>
+#include <kapi/system.hpp>
namespace kapi::system
{
- namespace
- {
- constexpr auto gdt_null_descriptor = arch::cpu::segment_descriptor{};
-
- constexpr auto gdt_kernel_code_descriptor = arch::cpu::segment_descriptor{
- .limit_low = 0xffff,
- .base_low = 0,
- .accessed = false,
- .read_write = false,
- .direction_or_conforming = false,
- .executable = true,
- .type = arch::cpu::segment_type::code_or_data,
- .privilege_level = 0,
- .present = true,
- .limit_high = 0xf,
- .long_mode = true,
- .protected_mode = false,
- .granularity = arch::cpu::segment_granularity::page,
- .base_high = 0,
- };
-
- constexpr auto gdt_kernel_data_descriptor = arch::cpu::segment_descriptor{
- .limit_low = 0xffff,
- .base_low = 0,
- .accessed = false,
- .read_write = true,
- .direction_or_conforming = false,
- .executable = false,
- .type = arch::cpu::segment_type::code_or_data,
- .privilege_level = 0,
- .present = true,
- .limit_high = 0xf,
- .long_mode = false,
- .protected_mode = true,
- .granularity = arch::cpu::segment_granularity::page,
- .base_high = 0,
- };
-
- constexpr auto gdt_user_code_descriptor = arch::cpu::segment_descriptor{
- .limit_low = 0xffff,
- .base_low = 0,
- .accessed = false,
- .read_write = false,
- .direction_or_conforming = false,
- .executable = true,
- .type = arch::cpu::segment_type::code_or_data,
- .privilege_level = 3,
- .present = true,
- .limit_high = 0xf,
- .long_mode = true,
- .protected_mode = false,
- .granularity = arch::cpu::segment_granularity::page,
- .base_high = 0,
- };
-
- constexpr auto gdt_user_data_descriptor = arch::cpu::segment_descriptor{
- .limit_low = 0xffff,
- .base_low = 0,
- .accessed = false,
- .read_write = true,
- .direction_or_conforming = false,
- .executable = false,
- .type = arch::cpu::segment_type::code_or_data,
- .privilege_level = 3,
- .present = true,
- .limit_high = 0xf,
- .long_mode = false,
- .protected_mode = false,
- .granularity = arch::cpu::segment_granularity::page,
- .base_high = 0,
- };
- } // namespace
-
- auto memory_initialized() -> void
- {
- auto static tss = arch::cpu::task_state_segment{};
- auto static tss_descriptor = arch::cpu::system_segment_descriptor{
- {
- .limit_low = (sizeof(tss) - 1) & 0xffff, // NOLINT(readability-magic-numbers)
- .base_low = std::bit_cast<std::uintptr_t>(&tss) & 0xffffff, // NOLINT(readability-magic-numbers)
- .accessed = false,
- .read_write = false,
- .direction_or_conforming = false,
- .executable = false,
- .type = arch::cpu::segment_type::system,
- .privilege_level = 0,
- .present = true,
- .limit_high = ((sizeof(tss) - 1) >> 16) & 0xf, // NOLINT(readability-magic-numbers)
- .long_mode = false,
- .protected_mode = false,
- .granularity = arch::cpu::segment_granularity::byte,
- .base_high = (std::bit_cast<std::uintptr_t>(&tss) >> 24) & 0xff, // NOLINT(readability-magic-numbers)
- },
- (std::bit_cast<std::uintptr_t>(&tss) >> 32) & 0xffff'ffff, // NOLINT(readability-magic-numbers)
- };
-
- auto static gdt = arch::cpu::global_descriptor_table{
- gdt_null_descriptor, gdt_kernel_code_descriptor, gdt_kernel_data_descriptor,
- gdt_user_code_descriptor, gdt_user_data_descriptor, tss_descriptor,
- };
-
- kstd::println("[x86_64:SYS] Reloading Global Descriptor Table.");
- gdt.load(1, 2);
-
- kstd::println("[x86_64:SYS] TODO: initialize Interrupt Descriptor Table.");
- }
+ 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/context_switching/main.hpp b/arch/x86_64/pre/include/arch/context_switching/main.hpp
deleted file mode 100644
index f8477ea..0000000
--- a/arch/x86_64/pre/include/arch/context_switching/main.hpp
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_MAIN_HPP
-#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_MAIN_HPP
-
-#include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp"
-#include "arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp"
-
-namespace teachos::arch::context_switching
-{
- /**
- * @brief Contains the references to the tables required for context switching
- */
- struct descriptor_tables
- {
- segment_descriptor_table::global_descriptor_table & gdt; ///< Reference to the global descriptor table.
- interrupt_descriptor_table::interrupt_descriptor_table & idt; ///< Reference to the interrupt descriptor table.
- };
-
- /**
- * @brief Creates the Interrupt Descriptor Table and Global Descriptor Table as a static variable the first time this
- * method is called and update IDTR and GDTR registers values.
- *
- * @note Subsequent calls after the first one, will simply return the previously created tables, but not update the
- * registers again.
- *
- * @return References to the statically created Interrupt Descriptor and Global Descriptor Table.
- */
- auto initialize_descriptor_tables() -> descriptor_tables;
-
- /**
- * @brief Switches from the current Kernel Mode (Level 0) to User Mode (Level 3). Will simply use predefined Segment
- * Selectors for the User Data and User Code Segment, which are Index 3 and 4 in the GDT respectively.
- */
- auto switch_to_user_mode() -> void;
-
- /**
- * @brief Switches from the current Code and Data Segment to the given Code and Data Segment.
- *
- * @note This method will additionally call initialize_descriptor_tables, to ensure the GDTR and IDTR have been setup
- * correctly before attempting to switch the context. This switch is achieved using a far return, which will once
- * executed call the given void function.
- *
- * @param data_segment Data Segment that the SS, DS; ES, FS and GS register will be set too.
- * @param code_segment Code Segment that the CS register will be set too.
- * @param return_function Function that will be called once the switch has been achieved.
- */
- auto switch_context(interrupt_descriptor_table::segment_selector data_segment,
- interrupt_descriptor_table::segment_selector code_segment, void (*return_function)()) -> void;
-
-} // namespace teachos::arch::context_switching
-
-#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_MAIN_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/syscall/main.hpp b/arch/x86_64/pre/include/arch/context_switching/syscall/main.hpp
deleted file mode 100644
index f507c61..0000000
--- a/arch/x86_64/pre/include/arch/context_switching/syscall/main.hpp
+++ /dev/null
@@ -1,91 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_MAIN_HPP
-#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_MAIN_HPP
-
-#include <cstdint>
-
-namespace teachos::arch::context_switching::syscall
-{
- /**
- * @brief Possible syscall implementation that should actually be called.
- *
- * @note Attempts to reflect the Linux interface partially. See https://filippo.io/linux-syscall-table/ for more
- * information.
- */
- enum class type : uint64_t
- {
- WRITE = 1U, ///< Loads the arg_0 parameter as an address pointing to a const char array, which will then be printed
- ///< onto the VGA buffer screen.
- EXPAND_HEAP = 2U, /// Expands the User Heap by additonally mapping 100 KiB of virtual page memory. Ignores the
- /// parameters and uses them as out parameters instead, where arg_0 is the start of the newly
- /// mapped heap area and arg_1 is the size of the entire area. Can be less than 100 KiB if less
- /// space remains.
- ASSERT = 3U, /// Loads the arg_0 parameter as a boolean which needs to be true or it will print the message in
- /// arg_1 parameter onto the VGA buffer screen, keep it as a nullptr if it shouldn't print anything
- /// and then it halts the further execution of the application.
- };
-
- /**
- * @brief Possible error codes that can be returned by the different syscall methods called depending on the type
- * enum.
- */
- enum class error : uint8_t
- {
- OK = 0U, ///< No error occured in syscall.
- OUT_OF_MEMORY = 1U, ///< Expanding heap failed because we have run out of mappable virtual address space.
- };
-
- /**
- * @brief Allows to convert the error enum type into a boolean directly. Where any code besides 0 being no error, will
- * return true. The remaining errors return true.
- *
- * @param e Error code that was returned by the syscall.
- * @return Return true if there was no error and false otherwise.
- */
- constexpr bool operator!(error e)
- {
- return e == error::OK;
- }
-
- /**
- * @brief Maximum amount of arguments that can be passed to a syscall. Default value is 0 and arguments are only ever
- * used depending on the actual enum type and if the method requires thoose parameters.
- */
- struct arguments
- {
- uint64_t arg_0{}; ///< First optional paramter to the syscall representing the RDI register.
- uint64_t arg_1{}; ///< Second optional paramter to the syscall representing the RSI register.
- uint64_t arg_2{}; ///< Third optional paramter to the syscall representing the RDX register.
- uint64_t arg_3{}; ///< Fourth optional paramter to the syscall representing the R10 register.
- uint64_t arg_4{}; ///< Fifth optional paramter to the syscall representing the R8 register.
- uint64_t arg_5{}; ///< Sixth optional paramter to the syscall representing the R9 register.
- };
-
- /**
- * @brief Response of a systemcall always containin an error code, signaling if the syscall even succeeded or not.
- * Additionally it may contain up to 6 return values in the values struct.
- */
- struct response
- {
- error error_code; ///< Error code returned by the syscall. If it failed all the values will be 0.
- arguments values = {}; ///< Optional return values of the syscall implementation.
- };
-
- /**
- * @brief Calls the method associated with the given syscall number and passes the given optional arguments to it,
- * over the RDI, RSI, RDX, R10, R8 and R9 register.
- *
- * @param syscall_number Syscall method that should be called. See enum values in type for possible implemented
- * methods.
- * @param args Optional arguments passable to the different syscall methods, called depending on the syscall_number.
- * Not passing the required parameters to the method, will result in passing 0 instead, which might make the fail or
- * not function correctly.
- * @return The syscall implementation always returns a bool-convertable error code converting to true if the syscall
- * failed or false if it didn't. Additionally it might pase additional values besides the error code, they will be set
- * in the arguments struct. So the value can be read and used for further processing.
- */
- [[gnu::section(".user_text")]]
- auto syscall(type syscall_number, arguments args = {}) -> response;
-
-} // namespace teachos::arch::context_switching::syscall
-
-#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_MAIN_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/syscall/syscall_enable.hpp b/arch/x86_64/pre/include/arch/context_switching/syscall/syscall_enable.hpp
deleted file mode 100644
index 8cb468a..0000000
--- a/arch/x86_64/pre/include/arch/context_switching/syscall/syscall_enable.hpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_ENABLE_HPP
-#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_ENABLE_HPP
-
-namespace teachos::arch::context_switching::syscall
-{
- /**
- * @brief Enables and sets up internal CPU registers to allow for syscall to function correctly and switch context
- * temporarily back to the kernel level.
- *
- * @note Configures the Model Specific Register required by syscall (LSTAR, FMASK, STAR) with the correct values so
- * that the syscall_handler is called and sets the System Call Extension bit on the EFER flags to allow for syscall
- * to be used.
- */
- auto enable_syscall() -> void;
-
-} // namespace teachos::arch::context_switching::syscall
-
-#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_ENABLE_HPP
diff --git a/arch/x86_64/pre/include/arch/context_switching/syscall/syscall_handler.hpp b/arch/x86_64/pre/include/arch/context_switching/syscall/syscall_handler.hpp
deleted file mode 100644
index 2e7bcd1..0000000
--- a/arch/x86_64/pre/include/arch/context_switching/syscall/syscall_handler.hpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_HANDLER_HPP
-#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_HANDLER_HPP
-
-#include <cstdint>
-
-namespace teachos::arch::context_switching::syscall
-{
- /**
- * @brief Handler for SYSCALL instruction. Calls a specific implementation based
- * on the register RAX.
- *
- * @return Returns with LEAVE, SYSRETQ
- */
- auto syscall_handler() -> void;
-
-} // namespace teachos::arch::context_switching::syscall
-
-#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_HANDLER_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/include/arch/kernel/halt.hpp b/arch/x86_64/pre/include/arch/kernel/halt.hpp
deleted file mode 100644
index 377acc0..0000000
--- a/arch/x86_64/pre/include/arch/kernel/halt.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_KERNEL_HALT_HPP
-#define TEACHOS_ARCH_X86_64_KERNEL_HALT_HPP
-
-namespace teachos::arch::kernel
-{
- /**
- * @brief Halts the kernel execution, meaning any code after a call to this will not run anymore.
- */
- extern "C" [[noreturn]] auto halt() -> void;
-
-} // namespace teachos::arch::kernel
-
-#endif // TEACHOS_ARCH_X86_64_KERNEL_HALT_HPP
diff --git a/arch/x86_64/pre/include/arch/kernel/main.hpp b/arch/x86_64/pre/include/arch/kernel/main.hpp
deleted file mode 100644
index a13e5f4..0000000
--- a/arch/x86_64/pre/include/arch/kernel/main.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_KERNEL_MAIN_HPP
-#define TEACHOS_ARCH_X86_64_KERNEL_MAIN_HPP
-
-namespace teachos::arch::kernel
-{
- /**
- * @brief Initalizes the kernel system.
- */
- auto main() -> void;
-
-} // namespace teachos::arch::kernel
-
-#endif // TEACHOS_ARCH_X86_64_KERNEL_MAIN_HPP
diff --git a/arch/x86_64/pre/include/arch/user/main.hpp b/arch/x86_64/pre/include/arch/user/main.hpp
deleted file mode 100644
index c168a1f..0000000
--- a/arch/x86_64/pre/include/arch/user/main.hpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_USER_MAIN_HPP
-#define TEACHOS_ARCH_X86_64_USER_MAIN_HPP
-
-namespace teachos::arch::user
-{
- /**
- * @brief User Main method. If this method finishes there is no code left to run and the whole OS will shut down.
- * Additionally this main method is executed at Ring 3 and accessing CPU Registers or Kernel level functionality can
- * only be done over syscalls and not directly anymore.
- */
- [[gnu::section(".user_text")]]
- auto main() -> void;
-
-} // namespace teachos::arch::user
-
-#endif // TEACHOS_ARCH_X86_64_USER_MAIN_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/context_switching/main.cpp b/arch/x86_64/pre/src/context_switching/main.cpp
deleted file mode 100644
index 3eb6dae..0000000
--- a/arch/x86_64/pre/src/context_switching/main.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-#include "arch/context_switching/main.hpp"
-
-#include "arch/boot/pointers.hpp"
-#include "arch/context_switching/syscall/syscall_enable.hpp"
-#include "arch/kernel/cpu/call.hpp"
-#include "arch/kernel/cpu/if.hpp"
-#include "arch/kernel/cpu/segment_register.hpp"
-#include "arch/kernel/cpu/tr.hpp"
-#include "arch/user/main.hpp"
-
-namespace teachos::arch::context_switching
-{
- namespace
- {
- constexpr interrupt_descriptor_table::segment_selector KERNEL_CODE_SEGMENT_SELECTOR{
- 1U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL};
- constexpr kernel::cpu::far_pointer KERNEL_CODE_POINTER{&kernel::cpu::reload_data_segment_registers,
- KERNEL_CODE_SEGMENT_SELECTOR};
- constexpr context_switching::interrupt_descriptor_table::segment_selector USER_CODE_SEGMENT_SELECTOR{
- 3U, context_switching::interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_USER};
- constexpr context_switching::interrupt_descriptor_table::segment_selector USER_DATA_SEGMENT_SELECTOR{
- 4U, context_switching::interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_USER};
-
- auto reload_gdtr() -> void
- {
- kernel::cpu::call(KERNEL_CODE_POINTER);
- }
- } // namespace
-
- auto initialize_descriptor_tables() -> descriptor_tables
- {
- bool static initalized = false;
-
- if (!initalized)
- {
- kernel::cpu::clear_interrupt_flag();
-
- segment_descriptor_table::update_gdtr();
- interrupt_descriptor_table::update_interrupt_descriptor_table_register();
-
- reload_gdtr();
- segment_descriptor_table::update_tss_register();
-
- kernel::cpu::set_interrupt_flag();
- initalized = true;
- }
-
- descriptor_tables tables = {segment_descriptor_table::get_or_create_gdt(),
- interrupt_descriptor_table::get_or_create_interrupt_descriptor_table()};
- return tables;
- }
-
- auto switch_to_user_mode() -> void
- {
- syscall::enable_syscall();
- switch_context(USER_DATA_SEGMENT_SELECTOR, USER_CODE_SEGMENT_SELECTOR, user::main);
- }
-
- auto switch_context(interrupt_descriptor_table::segment_selector data_segment,
- interrupt_descriptor_table::segment_selector code_segment, void (*return_function)()) -> void
- {
- (void)initialize_descriptor_tables();
- kernel::cpu::set_data_segment_registers(data_segment);
- kernel::cpu::set_code_segment_register(data_segment, code_segment, reinterpret_cast<uint64_t>(return_function));
- }
-} // namespace teachos::arch::context_switching
diff --git a/arch/x86_64/pre/src/context_switching/syscall/main.cpp b/arch/x86_64/pre/src/context_switching/syscall/main.cpp
deleted file mode 100644
index b4ab468..0000000
--- a/arch/x86_64/pre/src/context_switching/syscall/main.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#include "arch/context_switching/syscall/main.hpp"
-
-namespace teachos::arch::context_switching::syscall
-{
- auto syscall(type syscall_number, arguments args) -> response
- {
- asm volatile("mov %[input], %%rax"
- : /* no output from call */
- : [input] "m"(syscall_number)
- : "memory");
-
- asm volatile("mov %[input], %%rdi " : /* no output from call */ : [input] "m"(args.arg_0) : "memory");
- asm volatile("mov %[input], %%rsi" : /* no output from call */ : [input] "m"(args.arg_1) : "memory");
- asm volatile("mov %[input], %%rdx" : /* no output from call */ : [input] "m"(args.arg_2) : "memory");
- asm volatile("mov %[input], %%r10" : /* no output from call */ : [input] "m"(args.arg_3) : "memory");
- asm volatile("mov %[input], %%r8" : /* no output from call */ : [input] "m"(args.arg_4) : "memory");
- asm volatile("mov %[input], %%r9" : /* no output from call */ : [input] "m"(args.arg_5) : "memory");
-
- asm volatile("syscall");
-
- arguments values{};
- asm volatile("mov %%rdi, %[output]" : [output] "=m"(values.arg_0));
- asm volatile("mov %%rsi, %[output]" : [output] "=m"(values.arg_1));
- asm volatile("mov %%rdx, %[output]" : [output] "=m"(values.arg_2));
- asm volatile("mov %%r10, %[output]" : [output] "=m"(values.arg_3));
- asm volatile("mov %%r8, %[output]" : [output] "=m"(values.arg_4));
- asm volatile("mov %%r9, %[output]" : [output] "=m"(values.arg_5));
-
- error error_code{};
- asm volatile("mov %%al, %[output]" : [output] "=m"(error_code));
-
- return {error_code, values};
- }
-
-} // namespace teachos::arch::context_switching::syscall
diff --git a/arch/x86_64/pre/src/context_switching/syscall/syscall_enable.cpp b/arch/x86_64/pre/src/context_switching/syscall/syscall_enable.cpp
deleted file mode 100644
index dbb3ed9..0000000
--- a/arch/x86_64/pre/src/context_switching/syscall/syscall_enable.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "arch/context_switching/syscall/syscall_enable.hpp"
-
-#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp"
-#include "arch/context_switching/syscall/syscall_handler.hpp"
-#include "arch/kernel/cpu/msr.hpp"
-
-namespace teachos::arch::context_switching::syscall
-{
- namespace
- {
- constexpr interrupt_descriptor_table::segment_selector KERNEL_CODE_SEGMENT_SELECTOR{
- 1U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL};
-
- constexpr auto IA32_STAR_ADDRESS = 0xC000'0081;
- constexpr auto IA32_LSTAR_ADDRESS = 0xC000'0082;
- constexpr auto IA32_FMASK_ADDRESS = 0xC000'0084;
-
- } // namespace
-
- auto enable_syscall() -> void
- {
- uint64_t const syscall_function = reinterpret_cast<uint64_t>(syscall_handler);
- kernel::cpu::write_msr(IA32_LSTAR_ADDRESS, syscall_function);
- kernel::cpu::write_msr(IA32_FMASK_ADDRESS, 0U);
-
- uint64_t const kernel_cs = KERNEL_CODE_SEGMENT_SELECTOR;
- uint64_t const star_value = (kernel_cs << 32) | (kernel_cs << 48);
- kernel::cpu::write_msr(IA32_STAR_ADDRESS, star_value);
-
- kernel::cpu::set_efer_bit(kernel::cpu::efer_flags::SCE);
- }
-} // namespace teachos::arch::context_switching::syscall
diff --git a/arch/x86_64/pre/src/context_switching/syscall/syscall_handler.cpp b/arch/x86_64/pre/src/context_switching/syscall/syscall_handler.cpp
deleted file mode 100644
index c120f77..0000000
--- a/arch/x86_64/pre/src/context_switching/syscall/syscall_handler.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-#include "arch/context_switching/syscall/syscall_handler.hpp"
-
-#include "arch/context_switching/syscall/main.hpp"
-#include "arch/exception_handling/assert.hpp"
-#include "arch/exception_handling/panic.hpp"
-#include "arch/memory/heap/global_heap_allocator.hpp"
-#include "arch/memory/main.hpp"
-#include "arch/video/vga/text.hpp"
-
-namespace teachos::arch::context_switching::syscall
-{
-
- namespace
- {
- auto write_to_vga_buffer(uint64_t buffer) -> response
- {
- video::vga::text::write(reinterpret_cast<char const *>(buffer),
- video::vga::text::common_attributes::green_on_black);
- video::vga::text::newline();
- return {error::OK};
- }
-
- auto expand_user_heap() -> response
- {
- auto static current_heap_end = memory::heap::USER_HEAP_START;
- uint64_t const heap_start = current_heap_end;
- memory::remap_heap(heap_start, memory::heap::USER_HEAP_SIZE, memory::paging::entry::USER_ACCESSIBLE);
- current_heap_end += memory::heap::USER_HEAP_SIZE;
- return {
- error::OK,
- {heap_start, memory::heap::USER_HEAP_SIZE}
- };
- }
- } // namespace
-
- auto syscall_handler() -> void
- {
- // Saving state of rcx and r11 because it is required by sysretq to function.
- // Calls to other functions potentially overwrite these registers, because of
- // callee saved calling convention.
- uint64_t return_instruction_pointer, rflags = {};
- asm volatile("mov %%rcx, %[output]" : [output] "=m"(return_instruction_pointer));
- asm volatile("mov %%r11, %[output]" : [output] "=m"(rflags));
-
- uint64_t syscall_number, arg_0, arg_1, arg_2, arg_3, arg_4, arg_5 = {};
- asm volatile("mov %%rdi, %[output]" : [output] "=m"(arg_0));
- asm volatile("mov %%rsi, %[output]" : [output] "=m"(arg_1));
- asm volatile("mov %%rdx, %[output]" : [output] "=m"(arg_2));
- asm volatile("mov %%r10, %[output]" : [output] "=m"(arg_3));
- asm volatile("mov %%r8, %[output]" : [output] "=m"(arg_4));
- asm volatile("mov %%r9, %[output]" : [output] "=m"(arg_5));
-
- // RAX is read last, because paired with our type enum, we can use it to check
- // if the register has been written by the compiled code between executing the syscall
- // and now.
- asm volatile("mov %%rax, %[output]" : [output] "=m"(syscall_number));
-
- response result;
- switch (static_cast<type>(syscall_number))
- {
- case type::WRITE:
- result = write_to_vga_buffer(arg_0);
- break;
- case type::EXPAND_HEAP:
- result = expand_user_heap();
- break;
- case type::ASSERT:
- teachos::arch::exception_handling::assert(arg_0, reinterpret_cast<char const *>(arg_1));
- break;
- default:
- teachos::arch::exception_handling::panic("[Syscall Handler] Invalid syscall number");
- break;
- }
-
- asm volatile("mov %[input], %%rax"
- : /* no output from call */
- : [input] "m"(result.error_code)
- : "memory");
-
- asm volatile("mov %[input], %%rdi"
- : /* no output from call */
- : [input] "m"(result.values.arg_0)
- : "memory");
- asm volatile("mov %[input], %%rsi"
- : /* no output from call */
- : [input] "m"(result.values.arg_1)
- : "memory");
- asm volatile("mov %[input], %%rdx"
- : /* no output from call */
- : [input] "m"(result.values.arg_2)
- : "memory");
- asm volatile("mov %[input], %%r10"
- : /* no output from call */
- : [input] "m"(result.values.arg_3)
- : "memory");
- asm volatile("mov %[input], %%r8"
- : /* no output from call */
- : [input] "m"(result.values.arg_4)
- : "memory");
- asm volatile("mov %[input], %%r9"
- : /* no output from call */
- : [input] "m"(result.values.arg_5)
- : "memory");
-
- asm volatile("mov %[input], %%rcx"
- : /* no output from call */
- : [input] "m"(return_instruction_pointer)
- : "memory");
- asm volatile("mov %[input], %%r11"
- : /* no output from call */
- : [input] "m"(rflags)
- : "memory");
-
- // Additionally call leave, because x86 allocates stack space for the internal variables. If we do not clean up this
- // newly created stack frame the syscall instruction that landed in this syscall_handler, will never return to the
- // method that originally called it, because the RIP has not been restored from the previous stack frame.
- asm volatile("leave\n"
- "sysretq");
- }
-
-} // namespace teachos::arch::context_switching::syscall
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/pre/src/kernel/main.cpp b/arch/x86_64/pre/src/kernel/main.cpp
deleted file mode 100644
index 43b5f90..0000000
--- a/arch/x86_64/pre/src/kernel/main.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-#include "arch/kernel/main.hpp"
-
-#include "arch/boot/pointers.hpp"
-#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp"
-#include "arch/context_switching/main.hpp"
-#include "arch/kernel/cpu/if.hpp"
-#include "arch/kernel/cpu/segment_register.hpp"
-#include "arch/memory/heap/bump_allocator.hpp"
-#include "arch/memory/heap/global_heap_allocator.hpp"
-#include "arch/memory/main.hpp"
-#include "arch/memory/multiboot/reader.hpp"
-#include "arch/stl/vector.hpp"
-#include "arch/video/vga/text.hpp"
-
-namespace teachos::arch::kernel
-{
- auto stack_overflow_test(int count) -> int
- {
- int test[5000] = {};
- if (test[0] == 0xFFFF)
- {
- return count;
- }
- count = stack_overflow_test(count);
- return count++;
- }
-
- auto heap_test() -> void
- {
- auto test2 = new memory::multiboot::memory_information{};
- auto test3 = new memory::multiboot::memory_information{};
- auto test4 = *test2;
- auto test5 = *test3;
- test4.kernel_end = 5000;
- test5.kernel_end = 3000;
- auto test6 = test4.kernel_end;
- auto test7 = test5.kernel_end;
- auto test8 = memory::multiboot::read_multiboot2();
- if (test6 && test7 && test8.kernel_end)
- {
- video::vga::text::write("Heap test successful", video::vga::text::common_attributes::green_on_black);
- }
- test2->kernel_end = 2000;
- test2->kernel_start = 1000;
- test2->multiboot_start = 2000;
- delete test2;
- delete test3;
-
- auto test9 = new int(50);
- delete test9;
- }
-
- auto main() -> void
- {
- video::vga::text::clear();
- video::vga::text::cursor(false);
- video::vga::text::write("TeachOS is starting up...", video::vga::text::common_attributes::green_on_black);
- video::vga::text::newline();
-
- memory::initialize_memory_management();
- // stack_overflow_test(0);
-
- memory::heap::global_heap_allocator::register_heap_allocator(memory::heap::heap_allocator_type::LINKED_LIST);
- // heap_test();
-
- auto address = memory::heap::global_heap_allocator::kmalloc(8U);
- (void)address;
-
- context_switching::switch_to_user_mode();
- }
-} // namespace teachos::arch::kernel
diff --git a/arch/x86_64/pre/src/user/main.cpp b/arch/x86_64/pre/src/user/main.cpp
deleted file mode 100644
index 8b07e4a..0000000
--- a/arch/x86_64/pre/src/user/main.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#include "arch/user/main.hpp"
-
-#include "arch/context_switching/syscall/main.hpp"
-#include "arch/memory/heap/global_heap_allocator.hpp"
-
-#include <algorithm>
-#include <array>
-#include <atomic>
-#include <ranges>
-
-namespace teachos::arch::user
-{
- auto main() -> void
- {
- constexpr char syscall_message[] = "Successfully entered user mode and wrote to VGA buffer via syscall!";
- context_switching::syscall::syscall(context_switching::syscall::type::WRITE,
- {reinterpret_cast<uint64_t>(&syscall_message)});
-
- // Test C++ standard library
- std::array<std::atomic<uint8_t>, 4> array_test = {std::atomic<uint8_t>{5}, std::atomic<uint8_t>{10},
- std::atomic<uint8_t>{15}, std::atomic<uint8_t>{20}};
- std::ranges::for_each(array_test, [](auto & item) {
- auto value = item.load();
- uint8_t max_value = std::max(value, uint8_t{10});
- item.exchange(max_value + 2);
- });
-
- auto address = new uint64_t{10U};
- (void)address;
-
- for (;;)
- {
- }
- }
-} // namespace teachos::arch::user
diff --git a/arch/x86_64/scripts/kernel.ld b/arch/x86_64/scripts/kernel.ld
index a429570..dbb0f8f 100644
--- a/arch/x86_64/scripts/kernel.ld
+++ b/arch/x86_64/scripts/kernel.ld
@@ -72,6 +72,12 @@ SECTIONS
.kernel_rodata ALIGN(4K) : AT (ADDR (.kernel_rodata) - TEACHOS_VMA)
{
*(.rodata*)
+
+ . = ALIGN(8);
+
+ PROVIDE(__start_fs_types = .);
+ KEEP(*(fs_types));
+ PROVIDE(__stop_fs_types = .);
} :kernel_rodata
.kernel_data ALIGN(4K) : AT (ADDR (.kernel_data) - TEACHOS_VMA)
diff --git a/arch/x86_64/support/grub.cfg.in b/arch/x86_64/support/grub.cfg.in
index 49f19ce..45c3356 100644
--- a/arch/x86_64/support/grub.cfg.in
+++ b/arch/x86_64/support/grub.cfg.in
@@ -3,5 +3,8 @@ default=0
menuentry "TeachOS" {
multiboot2 /$<TARGET_FILE_NAME:kernel>
+ module2 /modules/ext2_4KB_fs.img
+ module2 /modules/ext2_1KB_fs.img
+ module2 /modules/ext2_2KB_fs.img
boot
} \ No newline at end of file
diff --git a/arch/x86_64/support/modules/README.md b/arch/x86_64/support/modules/README.md
new file mode 100644
index 0000000..6d235a7
--- /dev/null
+++ b/arch/x86_64/support/modules/README.md
@@ -0,0 +1,130 @@
+# Default images
+The default images contain predefined data and structures that are specifically designed for testing purposes.
+The ext2_4KB_fs image is intentionally fragmented, as some files were created and deleted before additional files were added, resulting in a non-contiguous layout.
+
+## ext2_1KB_fs
+.
+./lost+found
+./archiv
+./archiv/2024.img
+./archiv/2025.img
+./archiv/mnt
+./closed.txt
+./information
+./information/info_1.txt
+./information/info_2.txt
+./symlinks
+./symlinks/info_1_absolute -> /information/info_1.txt
+./symlinks/info_1_relative -> ../information/info_1.txt
+./symlinks/information_directory_absolute -> /information
+./symlinks/information_directory_relative -> ../information
+./symlinks/invalid_absolute -> /invalid/non_existant.txt
+./symlinks/invalid_relative -> ../invalid/non_existant.txt
+./symlinks/symloop_a -> ./symloop_b
+./symlinks/symloop_b -> /symlinks/symloop_a
+./symlinks/traverse_back_5_times -> ../../../../../
+
+### 2024.img
+(ext2 filesystem with 2KB Block size)
+.
+./lost+found
+./sheep_1.txt
+./sheep_2.txt
+./stable/pig_1.txt
+./stable/pig_2.txt
+./stable/pig_3.txt
+./symlinks
+./symlinks/traverse_back_twice -> ../../
+
+### 2025.img
+(ext2 filesystem 4KB Block size)
+.
+./lost+found
+./dev
+./dev/image_1.txt
+./dev/image_2.txt
+./snake_1.txt
+./snake_2.txt
+./petting_zoo/goat_1.txt
+./petting_zoo/goat_2.txt
+./petting_zoo/chicken_coop
+./petting_zoo/chicken_coop/chicken_1.txt
+./petting_zoo/chicken_coop/chicken_2.txt
+./petting_zoo/chicken_coop/chicken_3.txt
+
+## ext2_2KB_fs
+.
+./lost+found
+./monkey_house
+./monkey_house/infrastructure
+./monkey_house/infrastructure/info.txt
+./monkey_house/infrastructure/water.txt
+./monkey_house/monkey_1.txt
+./monkey_house/monkey_2.txt
+./monkey_house/monkey_3.txt
+./monkey_house/caretaker
+./monkey_house/caretaker/isabelle.txt
+./monkey_house/caretaker/peter.txt
+./symlinks/leave_and_reenter_mount -> ../../archiv/../information/monkey_house
+
+## ext2_4KB_fs
+.
+./lost+found
+./entrance
+./entrance/tickets.txt
+./entrance/map.txt
+./enclosures
+./enclosures/lion_house
+./enclosures/lion_house/cage_a
+./enclosures/lion_house/cage_a/history.txt
+./enclosures/lion_house/cage_a/animals.txt
+./enclosures/lion_house/cage_b
+./enclosures/lion_house/cage_b/animals.txt
+./enclosures/lion_house/cage_b/history.txt
+./enclosures/lion_house/symlink_chain_2 -> /entrance/../enclosures/aquarium/symlink_chain_3
+./enclosures/elephant_house
+./enclosures/elephant_house/elephant_1.txt
+./enclosures/aquarium
+./enclosures/aquarium/spawn_fish.sh
+./enclosures/aquarium/symlink_chain_3 -> ../../entrance
+./enclosures/aquarium/tank_1
+./enclosures/aquarium/tank_1/fish_1.txt
+./enclosures/aquarium/tank_1/fish_2.txt
+./enclosures/aquarium/tank_1/fish_3.txt
+./enclosures/aquarium/tank_1/fish_4.txt
+./enclosures/aquarium/tank_2
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_1.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_2.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_3.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_4.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_5.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_6.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_7.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_8.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_9.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_10.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_11.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_12.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_13.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_14.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_15.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_16.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_17.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_18.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_19.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_20.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_21.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_22.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_23.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_24.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_25.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_26.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_27.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_28.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_29.txt
+./enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_30.txt
+./enclosures/info.txt
+./info.txt
+./symlinks
+./symlinks/symlink_chain_1 -> ../enclosures/lion_house/symlink_chain_2
+./symlinks/very_long_symlink -> ../enclosures/aquarium/tank_2/this_is_a_very_very_long_fish_filename_that_keeps_going_and_going_until_it_almost_breaks_linux_filesystem_limits_for_testing_purposes_and_we_add_more_characters_to_make_it_even_longer_30.txt
diff --git a/arch/x86_64/support/modules/ext2_1KB_fs.img b/arch/x86_64/support/modules/ext2_1KB_fs.img
new file mode 100644
index 0000000..a5202ca
--- /dev/null
+++ b/arch/x86_64/support/modules/ext2_1KB_fs.img
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:98ac3c1be872806e25fb14eea168ca79a91959f4e6a5ac3d00c5d8224c1f73a3
+size 10485760
diff --git a/arch/x86_64/support/modules/ext2_2KB_fs.img b/arch/x86_64/support/modules/ext2_2KB_fs.img
new file mode 100644
index 0000000..7f297f0
--- /dev/null
+++ b/arch/x86_64/support/modules/ext2_2KB_fs.img
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6d9e872916e7d9107b321cc007e151899d5f19400a694666c0b24d482aef61ca
+size 5242880
diff --git a/arch/x86_64/support/modules/ext2_4KB_fs.img b/arch/x86_64/support/modules/ext2_4KB_fs.img
new file mode 100644
index 0000000..c3f6daf
--- /dev/null
+++ b/arch/x86_64/support/modules/ext2_4KB_fs.img
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:026ca30269dbd80beb2dd74677c94676d1d4a7f6b5fe406c4ddb82836ba2dc00
+size 10485760