From bd585306e31889ee4fce60abb79bc3b3a58e2b84 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 6 Apr 2026 13:11:15 +0200 Subject: kapi: add basic ACPI support --- kernel/include/kernel/memory/block_list_allocator.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'kernel') diff --git a/kernel/include/kernel/memory/block_list_allocator.hpp b/kernel/include/kernel/memory/block_list_allocator.hpp index f319097..de89f3b 100644 --- a/kernel/include/kernel/memory/block_list_allocator.hpp +++ b/kernel/include/kernel/memory/block_list_allocator.hpp @@ -43,10 +43,10 @@ namespace kernel::memory private: struct block_header final { - kstd::units::bytes usable_size; - bool free; - block_header * next; - block_header * prev; + kstd::units::bytes usable_size{}; + bool free{}; + block_header * next{}; + block_header * prev{}; }; //! The size of the metadata required for each allocated block. @@ -87,4 +87,4 @@ namespace kernel::memory } // namespace kernel::memory -#endif \ No newline at end of file +#endif -- cgit v1.2.3 From 6e54333bcc08ddd8dbcb6aa9c3404001c309ec74 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 6 Apr 2026 13:27:22 +0200 Subject: kapi: move independent implementation to kernel --- kernel/CMakeLists.txt | 1 + kernel/kapi/acpi.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 kernel/kapi/acpi.cpp (limited to 'kernel') diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 9868eb9..ab77467 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -1,5 +1,6 @@ add_library("kernel_objs" OBJECT # Platform-independent KAPI implementation + "kapi/acpi.cpp" "kapi/boot_modules.cpp" "kapi/cio.cpp" "kapi/cpu.cpp" diff --git a/kernel/kapi/acpi.cpp b/kernel/kapi/acpi.cpp new file mode 100644 index 0000000..aa0066d --- /dev/null +++ b/kernel/kapi/acpi.cpp @@ -0,0 +1,68 @@ +#include "kapi/acpi.hpp" + +#include "kapi/memory.hpp" + +#include + +#include +#include +#include +#include +#include +#include + +namespace kapi::acpi +{ + + namespace + { + constexpr auto validate_checksum(std::span data) -> bool + { + auto sum = std::ranges::fold_left( + data, std::uint8_t{}, [](std::uint8_t acc, auto byte) { return static_cast(byte) + acc; }); + return sum == 0; + } + } // namespace + + auto root_system_description_pointer::oem_id() const noexcept -> std::string_view + { + return {m_oem_id.data(), m_oem_id.size()}; + } + + auto root_system_description_pointer::revision() const noexcept -> std::uint8_t + { + return m_revision; + } + + auto root_system_description_pointer::signature() const noexcept -> std::string_view + { + return {m_signature.data(), m_signature.size()}; + } + + auto root_system_description_pointer::table_address() const noexcept -> memory::physical_address + { + auto raw = std::bit_cast(m_rsdt_address); + return memory::physical_address{static_cast(raw)}; + } + + auto root_system_description_pointer::validate() const noexcept -> bool + { + return validate_checksum({reinterpret_cast(this), sizeof(root_system_description_pointer)}); + } + + auto extended_system_description_pointer::length() const noexcept -> kstd::units::bytes + { + return kstd::units::bytes{m_length}; + } + + auto extended_system_description_pointer::table_address() const noexcept -> memory::physical_address + { + return memory::physical_address{std::bit_cast(m_xsdt_address)}; + } + + auto extended_system_description_pointer::validate() const noexcept -> bool + { + return validate_checksum({reinterpret_cast(this), m_length}); + } + +}; // namespace kapi::acpi -- cgit v1.2.3 From 3dcd14a0570fef3bcc68d7df42fe3ff4cd496f93 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 6 Apr 2026 14:47:37 +0200 Subject: kapi: hook ACPI initialization up to boot process --- kernel/CMakeLists.txt | 1 + kernel/include/kernel/acpi/manager.hpp | 26 ++++++++++++++++ kernel/kapi/acpi.cpp | 32 ++++++++++++++++---- kernel/src/acpi/manager.cpp | 54 ++++++++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 6 deletions(-) create mode 100644 kernel/include/kernel/acpi/manager.hpp create mode 100644 kernel/src/acpi/manager.cpp (limited to 'kernel') diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index ab77467..fc01723 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -14,6 +14,7 @@ add_library("kernel_objs" OBJECT "kstd/print.cpp" # Kernel Implementation + "src/acpi/manager.cpp" "src/memory/bitmap_allocator.cpp" "src/memory/block_list_allocator.cpp" "src/memory.cpp" diff --git a/kernel/include/kernel/acpi/manager.hpp b/kernel/include/kernel/acpi/manager.hpp new file mode 100644 index 0000000..fc76685 --- /dev/null +++ b/kernel/include/kernel/acpi/manager.hpp @@ -0,0 +1,26 @@ +#ifndef TEACHOS_KERNEL_ACPI_MANAGER_HPP +#define TEACHOS_KERNEL_ACPI_MANAGER_HPP + +#include "kapi/acpi.hpp" + +#include + +namespace kernel::acpi +{ + + struct manager + { + explicit manager(kapi::acpi::root_system_description_pointer const & sdp); + + auto load_tables() -> bool; + + private: + kapi::acpi::root_system_description_pointer const * m_sdp{}; + kapi::acpi::system_description_table_header const * m_rsdt{}; + kstd::vector m_tables{}; + bool m_extended{}; + }; + +} // namespace kernel::acpi + +#endif diff --git a/kernel/kapi/acpi.cpp b/kernel/kapi/acpi.cpp index aa0066d..787bcff 100644 --- a/kernel/kapi/acpi.cpp +++ b/kernel/kapi/acpi.cpp @@ -1,13 +1,18 @@ #include "kapi/acpi.hpp" #include "kapi/memory.hpp" +#include "kapi/system.hpp" + +#include "kernel/acpi/manager.hpp" #include #include +#include #include #include #include +#include #include #include @@ -16,12 +21,7 @@ namespace kapi::acpi namespace { - constexpr auto validate_checksum(std::span data) -> bool - { - auto sum = std::ranges::fold_left( - data, std::uint8_t{}, [](std::uint8_t acc, auto byte) { return static_cast(byte) + acc; }); - return sum == 0; - } + auto constinit manager = std::optional{}; } // namespace auto root_system_description_pointer::oem_id() const noexcept -> std::string_view @@ -65,4 +65,24 @@ namespace kapi::acpi return validate_checksum({reinterpret_cast(this), m_length}); } + auto init(root_system_description_pointer const & sdp) -> bool + { + auto static constinit initialized = std::atomic_flag{}; + if (initialized.test_and_set()) + { + system::panic("[OS::ACPI] The ACPI manager has already been initialized!"); + } + + manager.emplace(sdp); + return manager->load_tables(); + } + + auto validate_checksum(std::span data) -> bool + { + auto sum = std::ranges::fold_left(data, std::uint8_t{}, [](auto acc, auto byte) { + return static_cast(acc + static_cast(byte)); + }); + return sum == 0; + } + }; // namespace kapi::acpi diff --git a/kernel/src/acpi/manager.cpp b/kernel/src/acpi/manager.cpp new file mode 100644 index 0000000..6a17920 --- /dev/null +++ b/kernel/src/acpi/manager.cpp @@ -0,0 +1,54 @@ +#include "kernel/acpi/manager.hpp" + +#include "kapi/acpi.hpp" +#include "kapi/memory.hpp" +#include "kapi/system.hpp" + +#include + +namespace kernel::acpi +{ + + manager::manager(kapi::acpi::root_system_description_pointer const & sdp) + : m_sdp{&sdp} + { + if (m_sdp->signature() != "RSD PTR ") + { + kapi::system::panic("[OS:ACPI] Invalid RSDP signature!"); + } + + if (m_sdp->revision() >= 2) + { + auto const xsdp = static_cast(m_sdp); + if (!xsdp->validate()) + { + kapi::system::panic("[OS:ACPI] Invalid XSDP signature!"); + } + auto physical_extended_table_address = xsdp->table_address(); + auto linear_extended_table_address = kapi::memory::hhdm_to_linear(physical_extended_table_address); + m_rsdt = static_cast(linear_extended_table_address); + m_extended = true; + } + else + { + if (!m_sdp->validate()) + { + kapi::system::panic("[OS:ACPI] Invalid RSDP checksum!"); + } + auto physical_root_table_address = m_sdp->table_address(); + auto linear_root_table_address = kapi::memory::hhdm_to_linear(physical_root_table_address); + m_rsdt = static_cast(linear_root_table_address); + } + } + + auto manager::load_tables() -> bool + { + if (!kapi::acpi::validate_checksum({reinterpret_cast(m_rsdt), m_rsdt->length})) + { + kapi::system::panic("[OS:ACPI] Invalid RSDT checksum!"); + } + + return false; + } + +} // namespace kernel::acpi -- cgit v1.2.3 From 4d938cd31a35cd4322fe914edd568faa5391c9c2 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 6 Apr 2026 15:10:04 +0200 Subject: kernel/acpi: implement basic table discovery --- kernel/include/kernel/acpi/manager.hpp | 5 +++- kernel/kapi/acpi.cpp | 45 ++++++++++++++++++++++++++++++++++ kernel/src/acpi/manager.cpp | 42 +++++++++++++++++++++++++++++-- 3 files changed, 89 insertions(+), 3 deletions(-) (limited to 'kernel') diff --git a/kernel/include/kernel/acpi/manager.hpp b/kernel/include/kernel/acpi/manager.hpp index fc76685..437d4c8 100644 --- a/kernel/include/kernel/acpi/manager.hpp +++ b/kernel/include/kernel/acpi/manager.hpp @@ -3,8 +3,11 @@ #include "kapi/acpi.hpp" +#include #include +#include + namespace kernel::acpi { @@ -17,7 +20,7 @@ namespace kernel::acpi private: kapi::acpi::root_system_description_pointer const * m_sdp{}; kapi::acpi::system_description_table_header const * m_rsdt{}; - kstd::vector m_tables{}; + kstd::flat_map m_tables{}; bool m_extended{}; }; diff --git a/kernel/kapi/acpi.cpp b/kernel/kapi/acpi.cpp index 787bcff..998d7a0 100644 --- a/kernel/kapi/acpi.cpp +++ b/kernel/kapi/acpi.cpp @@ -65,6 +65,51 @@ namespace kapi::acpi return validate_checksum({reinterpret_cast(this), m_length}); } + [[nodiscard]] auto system_description_table_header::checksum() const noexcept -> std::uint8_t + { + return m_checksum; + } + + [[nodiscard]] auto system_description_table_header::creator_revision() const noexcept -> std::uint32_t + { + return m_creator_revision; + } + + [[nodiscard]] auto system_description_table_header::creator_id() const noexcept -> std::uint32_t + { + return m_creator_id; + } + + [[nodiscard]] auto system_description_table_header::length() const noexcept -> kstd::units::bytes + { + return kstd::units::bytes{m_length}; + } + + [[nodiscard]] auto system_description_table_header::oem_id() const noexcept -> std::string_view + { + return {m_oem_id.data(), m_oem_id.size()}; + } + + [[nodiscard]] auto system_description_table_header::oem_revision() const noexcept -> std::uint32_t + { + return m_oem_revision; + } + + [[nodiscard]] auto system_description_table_header::oem_table_id() const noexcept -> std::string_view + { + return {m_oem_table_id.data(), m_oem_table_id.size()}; + } + + [[nodiscard]] auto system_description_table_header::revision() const noexcept -> std::uint8_t + { + return m_revision; + } + + [[nodiscard]] auto system_description_table_header::signature() const noexcept -> std::string_view + { + return {m_signature.data(), m_signature.size()}; + } + auto init(root_system_description_pointer const & sdp) -> bool { auto static constinit initialized = std::atomic_flag{}; diff --git a/kernel/src/acpi/manager.cpp b/kernel/src/acpi/manager.cpp index 6a17920..180d458 100644 --- a/kernel/src/acpi/manager.cpp +++ b/kernel/src/acpi/manager.cpp @@ -4,7 +4,10 @@ #include "kapi/memory.hpp" #include "kapi/system.hpp" +#include + #include +#include namespace kernel::acpi { @@ -43,12 +46,47 @@ namespace kernel::acpi auto manager::load_tables() -> bool { - if (!kapi::acpi::validate_checksum({reinterpret_cast(m_rsdt), m_rsdt->length})) + if (!kapi::acpi::validate_checksum({reinterpret_cast(m_rsdt), m_rsdt->length().value})) { kapi::system::panic("[OS:ACPI] Invalid RSDT checksum!"); } - return false; + auto entry_size = m_extended ? sizeof(std::uint64_t) : sizeof(std::uint32_t); + auto entry_count = (m_rsdt->length().value - sizeof(kapi::acpi::system_description_table_header)) / entry_size; + auto entries_base = + reinterpret_cast(m_rsdt) + sizeof(kapi::acpi::system_description_table_header); + + for (std::size_t i = 0; i < entry_count; ++i) + { + auto physical_table_address = kapi::memory::physical_address{}; + + if (m_extended) + { + auto entry = reinterpret_cast(entries_base + (i * entry_size)); + physical_table_address = kapi::memory::physical_address{*entry}; + } + else + { + auto entry = reinterpret_cast(entries_base + (i * entry_size)); + physical_table_address = kapi::memory::physical_address{*entry}; + } + + auto linear_table_address = kapi::memory::hhdm_to_linear(physical_table_address); + auto table = static_cast(linear_table_address); + + if (!kapi::acpi::validate_checksum({reinterpret_cast(table), table->length().value})) + { + kstd::println(kstd::print_sink::stderr, "[OS:ACPI] Invalid table checksum!"); + } + else + { + kstd::println("[OS:ACPI] Found table: {}@{:#x}/{:#x} OEM: {} Rev: {}", table->signature(), linear_table_address, + physical_table_address, table->oem_id(), table->creator_revision()); + m_tables.emplace(table->signature(), table); + } + } + + return !m_tables.empty(); } } // namespace kernel::acpi -- cgit v1.2.3 From f456f1674d48932846eb7b5ec1df630ad67e7e3d Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 6 Apr 2026 17:24:36 +0200 Subject: kernel/acpi: discover local interrupt controllers --- kernel/CMakeLists.txt | 1 + kernel/include/kernel/acpi/manager.hpp | 3 ++ kernel/include/kernel/devices/cpu.hpp | 33 ++++++++++++ kernel/kapi/acpi.cpp | 43 ++++++++++++++- kernel/kapi/devices.cpp | 10 ++++ kernel/src/acpi/manager.cpp | 15 +++++- kernel/src/devices/cpu.cpp | 97 ++++++++++++++++++++++++++++++++++ kernel/src/main.cpp | 10 ++++ 8 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 kernel/include/kernel/devices/cpu.hpp create mode 100644 kernel/src/devices/cpu.cpp (limited to 'kernel') diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index fc01723..92e2bda 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -20,6 +20,7 @@ add_library("kernel_objs" OBJECT "src/memory.cpp" "src/devices/block_device.cpp" "src/devices/block_device_utils.cpp" + "src/devices/cpu.cpp" "src/devices/root_bus.cpp" "src/devices/storage/controller.cpp" "src/devices/storage/management.cpp" diff --git a/kernel/include/kernel/acpi/manager.hpp b/kernel/include/kernel/acpi/manager.hpp index 437d4c8..fae59a6 100644 --- a/kernel/include/kernel/acpi/manager.hpp +++ b/kernel/include/kernel/acpi/manager.hpp @@ -4,6 +4,7 @@ #include "kapi/acpi.hpp" #include +#include #include #include @@ -17,6 +18,8 @@ namespace kernel::acpi auto load_tables() -> bool; + auto get_table(std::string_view signature) -> kstd::observer_ptr; + private: kapi::acpi::root_system_description_pointer const * m_sdp{}; kapi::acpi::system_description_table_header const * m_rsdt{}; diff --git a/kernel/include/kernel/devices/cpu.hpp b/kernel/include/kernel/devices/cpu.hpp new file mode 100644 index 0000000..b056665 --- /dev/null +++ b/kernel/include/kernel/devices/cpu.hpp @@ -0,0 +1,33 @@ +#ifndef TEACHOS_KERNEL_DEVICES_CPU_HPP +#define TEACHOS_KERNEL_DEVICES_CPU_HPP + +#include "kapi/devices.hpp" + +#include +#include + +namespace kernel::devices +{ + + struct cpu final : kapi::devices::bus + { + struct core final : kapi::devices::bus + { + explicit core(std::size_t major_number, std::size_t minor_number, std::uint64_t hardware_id, bool is_bsp); + + [[nodiscard]] auto hardware_id() const -> std::uint64_t; + [[nodiscard]] auto is_bsp() const -> bool; + + private: + std::uint64_t m_hardware_id; + bool m_is_bsp; + }; + + explicit cpu(std::size_t major_number); + + auto probe() -> bool final; + }; + +} // namespace kernel::devices + +#endif \ No newline at end of file diff --git a/kernel/kapi/acpi.cpp b/kernel/kapi/acpi.cpp index 998d7a0..1283d7e 100644 --- a/kernel/kapi/acpi.cpp +++ b/kernel/kapi/acpi.cpp @@ -5,6 +5,7 @@ #include "kernel/acpi/manager.hpp" +#include #include #include @@ -110,12 +111,47 @@ namespace kapi::acpi return {m_signature.data(), m_signature.size()}; } + [[nodiscard]] auto madt_header::local_interrupt_controller_address() const noexcept -> memory::physical_address + { + return memory::physical_address{static_cast(m_local_interrupt_controller_address)}; + } + + [[nodiscard]] auto madt_header::flags() const noexcept -> std::uint32_t + { + return m_flags; + } + + [[nodiscard]] auto madt_subtable_header::type() const noexcept -> std::uint8_t + { + return m_type; + } + + [[nodiscard]] auto madt_subtable_header::length() const noexcept -> std::size_t + { + return m_length; + } + + [[nodiscard]] auto madt_local_apic::apic_id() const noexcept -> std::uint8_t + { + return m_apic_id; + } + + [[nodiscard]] auto madt_local_apic::flags() const noexcept -> std::uint32_t + { + return m_flags; + } + + [[nodiscard]] auto madt_local_apic::processor_id() const noexcept -> std::uint32_t + { + return m_processor_id; + } + auto init(root_system_description_pointer const & sdp) -> bool { auto static constinit initialized = std::atomic_flag{}; if (initialized.test_and_set()) { - system::panic("[OS::ACPI] The ACPI manager has already been initialized!"); + system::panic("[OS:ACPI] The ACPI manager has already been initialized!"); } manager.emplace(sdp); @@ -130,4 +166,9 @@ namespace kapi::acpi return sum == 0; } + auto get_table(std::string_view signature) -> kstd::observer_ptr + { + return manager->get_table(signature); + } + }; // namespace kapi::acpi diff --git a/kernel/kapi/devices.cpp b/kernel/kapi/devices.cpp index 031f2c9..b2911b0 100644 --- a/kernel/kapi/devices.cpp +++ b/kernel/kapi/devices.cpp @@ -1,7 +1,9 @@ #include "kapi/devices.hpp" +#include "kapi/acpi.hpp" #include "kapi/system.hpp" +#include "kernel/devices/cpu.hpp" #include "kernel/devices/root_bus.hpp" #include @@ -35,6 +37,14 @@ namespace kapi::devices auto & bus = root_bus.emplace(); register_device(bus); bus.init(); + + auto madt = kapi::acpi::get_table("APIC"); + if (madt) + { + auto cpu_major = allocate_major_number(); + auto cpu = kstd::make_unique(cpu_major); + bus.add_child(std::move(cpu)); + } } auto get_root_bus() -> bus & diff --git a/kernel/src/acpi/manager.cpp b/kernel/src/acpi/manager.cpp index 180d458..300b85e 100644 --- a/kernel/src/acpi/manager.cpp +++ b/kernel/src/acpi/manager.cpp @@ -4,10 +4,12 @@ #include "kapi/memory.hpp" #include "kapi/system.hpp" +#include #include #include #include +#include namespace kernel::acpi { @@ -80,8 +82,7 @@ namespace kernel::acpi } else { - kstd::println("[OS:ACPI] Found table: {}@{:#x}/{:#x} OEM: {} Rev: {}", table->signature(), linear_table_address, - physical_table_address, table->oem_id(), table->creator_revision()); + kstd::println("[OS:ACPI] Found '{}' ACPI table", table->signature()); m_tables.emplace(table->signature(), table); } } @@ -89,4 +90,14 @@ namespace kernel::acpi return !m_tables.empty(); } + auto manager::get_table(std::string_view signature) + -> kstd::observer_ptr + { + if (m_tables.contains(signature)) + { + return kstd::make_observer(m_tables.at(signature)); + } + return nullptr; + } + } // namespace kernel::acpi diff --git a/kernel/src/devices/cpu.cpp b/kernel/src/devices/cpu.cpp new file mode 100644 index 0000000..7147368 --- /dev/null +++ b/kernel/src/devices/cpu.cpp @@ -0,0 +1,97 @@ +#include "kernel/devices/cpu.hpp" + +#include "kapi/acpi.hpp" +#include "kapi/devices.hpp" + +#include +#include + +#include +#include +#include + +namespace kernel::devices +{ + + namespace + { + + auto process_madt(kstd::observer_ptr madt, kapi::devices::bus & cpu) -> void + { + auto static const core_major = kapi::devices::allocate_major_number(); + auto static const lapic_major = kapi::devices::allocate_major_number(); + + auto lapic_address = madt->local_interrupt_controller_address(); + + auto const * current = reinterpret_cast(madt.get()) + sizeof(kapi::acpi::madt_header); + auto const * end = reinterpret_cast(madt.get()) + madt->length(); + + auto bsp_found = false; + auto core_index = 0; + + while (current < end) + { + auto const * sub_table = reinterpret_cast(current); + if (sub_table->type() == 0) + { + auto const * local_apic = reinterpret_cast(sub_table); + if (local_apic->flags() & 0b11) + { + auto is_bsp = !bsp_found; + bsp_found = true; + + auto apic_id = local_apic->apic_id(); + auto core = kstd::make_unique(core_major, core_index, apic_id, is_bsp); + auto lapic = kapi::acpi::create_local_interrupt_controller(lapic_major, core_index, apic_id, lapic_address); + + core->add_child(std::move(lapic)); + cpu.add_child(std::move(core)); + + ++core_index; + } + } + + current += sub_table->length(); + } + + kstd::println("[OS:DEV] Discovered {} CPU cores", core_index); + } + + } // namespace + + cpu::core::core(std::size_t major_number, std::size_t minor_number, std::uint64_t hardware_id, bool is_bsp) + : kapi::devices::bus{major_number, minor_number, "cpu_core"} + , m_hardware_id{hardware_id} + , m_is_bsp{is_bsp} + {} + + auto cpu::core::hardware_id() const -> std::uint64_t + { + return m_hardware_id; + } + + auto cpu::core::is_bsp() const -> bool + { + return m_is_bsp; + } + + cpu::cpu(std::size_t major_number) + : kapi::devices::bus{major_number, 0, "cpu"} + {} + + auto cpu::probe() -> bool + { + auto madt = kapi::acpi::get_table("APIC"); + if (!madt) + { + kstd::println("[OS:DEV] Failed to find ACPI APIC table"); + return false; + } + + auto madt_header = static_cast(madt.get()); + process_madt(kstd::make_observer(madt_header), *this); + + return true; + } + +} // namespace kernel::devices \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 2eaa2d8..e704955 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,3 +1,4 @@ +#include "kapi/acpi.hpp" #include "kapi/boot_modules.hpp" #include "kapi/cio.hpp" #include "kapi/cpu.hpp" @@ -179,6 +180,15 @@ auto main() -> int kstd::println("[OS] Memory subsystem initialized."); kapi::system::memory_initialized(); + auto acpi_root_pointer = kapi::acpi::get_root_pointer(); + if (acpi_root_pointer && acpi_root_pointer->validate()) + { + if (kapi::acpi::init(*acpi_root_pointer)) + { + kstd::println("[OS] ACPI subsystem initialized."); + } + } + kapi::devices::init(); kstd::println("[OS] System root bus initialized."); -- cgit v1.2.3 From 8d08b3b905d211e989848e1abf3a8ff2535836c8 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 6 Apr 2026 18:13:21 +0200 Subject: kapi: extract more code to the kernel --- kernel/CMakeLists.txt | 2 ++ kernel/kapi/devices/bus.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++ kernel/kapi/devices/device.cpp | 35 +++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 kernel/kapi/devices/bus.cpp create mode 100644 kernel/kapi/devices/device.cpp (limited to 'kernel') diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 92e2bda..6e081bd 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -5,6 +5,8 @@ add_library("kernel_objs" OBJECT "kapi/cio.cpp" "kapi/cpu.cpp" "kapi/devices.cpp" + "kapi/devices/bus.cpp" + "kapi/devices/device.cpp" "kapi/interrupts.cpp" "kapi/memory.cpp" "kapi/system.cpp" diff --git a/kernel/kapi/devices/bus.cpp b/kernel/kapi/devices/bus.cpp new file mode 100644 index 0000000..68874c4 --- /dev/null +++ b/kernel/kapi/devices/bus.cpp @@ -0,0 +1,65 @@ +#include "kapi/devices/bus.hpp" + +#include "kapi/devices.hpp" +#include "kapi/system.hpp" + +#include +#include +#include +#include + +#include +#include +#include + +namespace kapi::devices +{ + bus::bus(std::size_t major, std::size_t minor, kstd::string const & name) + : device(major, minor, name) + {} + + auto bus::init() -> bool + { + if (m_initialized.test_and_set()) + { + return true; + } + + if (!probe()) + { + return false; + } + + return std::ranges::fold_left(m_devices, true, [&](bool acc, auto & child) -> bool { + kstd::println("[OS:DEV] Initializing child device {}@{}", child->name(), name()); + return child->init() && acc; + }); + } + + auto bus::add_child(kstd::unique_ptr child) -> void + { + auto observer = m_observers.emplace_back(child.get()); + m_devices.push_back(std::move(child)); + kapi::devices::register_device(*observer); + + if (m_initialized.test()) + { + kstd::println("[OS:DEV] Initializing child device {}@{}", observer->name(), name()); + if (!observer->init()) + { + kapi::system::panic("[OS:DEV] Failed to initialize child device"); + } + } + } + + [[nodiscard]] auto bus::children() const -> kstd::vector> const & + { + return m_observers; + } + + auto bus::probe() -> bool + { + return true; + } + +} // namespace kapi::devices \ No newline at end of file diff --git a/kernel/kapi/devices/device.cpp b/kernel/kapi/devices/device.cpp new file mode 100644 index 0000000..9f7a404 --- /dev/null +++ b/kernel/kapi/devices/device.cpp @@ -0,0 +1,35 @@ +#include "kapi/devices/device.hpp" + +#include + +#include + +namespace kapi::devices +{ + device::device(size_t major, size_t minor, kstd::string const & name) + : m_major(major) + , m_minor(minor) + , m_name(name) + {} + + [[nodiscard]] auto device::major() const -> size_t + { + return m_major; + } + + [[nodiscard]] auto device::minor() const -> size_t + { + return m_minor; + } + + [[nodiscard]] auto device::name() const -> kstd::string const & + { + return m_name; + } + + [[nodiscard]] auto device::is_block_device() const -> bool + { + return false; + } + +} // namespace kapi::devices \ No newline at end of file -- cgit v1.2.3 From f50815110789a0f8f6e5ca66ffd49b26578791a9 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 6 Apr 2026 18:43:28 +0200 Subject: kernel: generalize CPU discovery --- kernel/CMakeLists.txt | 1 + kernel/kapi/devices.cpp | 11 +++------ kernel/kapi/platform.cpp | 32 +++++++++++++++++++++++++ kernel/src/devices/cpu.cpp | 58 +++------------------------------------------- 4 files changed, 39 insertions(+), 63 deletions(-) create mode 100644 kernel/kapi/platform.cpp (limited to 'kernel') diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 6e081bd..22513ea 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -9,6 +9,7 @@ add_library("kernel_objs" OBJECT "kapi/devices/device.cpp" "kapi/interrupts.cpp" "kapi/memory.cpp" + "kapi/platform.cpp" "kapi/system.cpp" # KSTD OS Implementation diff --git a/kernel/kapi/devices.cpp b/kernel/kapi/devices.cpp index b2911b0..dad1fe4 100644 --- a/kernel/kapi/devices.cpp +++ b/kernel/kapi/devices.cpp @@ -1,6 +1,5 @@ #include "kapi/devices.hpp" -#include "kapi/acpi.hpp" #include "kapi/system.hpp" #include "kernel/devices/cpu.hpp" @@ -38,13 +37,9 @@ namespace kapi::devices register_device(bus); bus.init(); - auto madt = kapi::acpi::get_table("APIC"); - if (madt) - { - auto cpu_major = allocate_major_number(); - auto cpu = kstd::make_unique(cpu_major); - bus.add_child(std::move(cpu)); - } + auto cpu_major = allocate_major_number(); + auto cpu = kstd::make_unique(cpu_major); + bus.add_child(std::move(cpu)); } auto get_root_bus() -> bus & diff --git a/kernel/kapi/platform.cpp b/kernel/kapi/platform.cpp new file mode 100644 index 0000000..deb72de --- /dev/null +++ b/kernel/kapi/platform.cpp @@ -0,0 +1,32 @@ +#include "kapi/platform.hpp" + +#include "kapi/devices.hpp" + +#include "kernel/devices/cpu.hpp" + +#include + +#include +#include + +namespace kapi::platform +{ + + auto cpu_detected(kapi::devices::bus & bus, std::uint64_t hardware_id, bool is_bsp) -> bool + { + auto static const core_major = kapi::devices::allocate_major_number(); + auto static const interrupt_controller_major = kapi::devices::allocate_major_number(); + auto static core_index = 0uz; + + auto core = kstd::make_unique(core_major, core_index, hardware_id, is_bsp); + auto lapic = kapi::platform::create_core_interrupt_controller(interrupt_controller_major, core_index, hardware_id); + + core->add_child(std::move(lapic)); + bus.add_child(std::move(core)); + + ++core_index; + + return true; + } + +} // namespace kapi::platform \ No newline at end of file diff --git a/kernel/src/devices/cpu.cpp b/kernel/src/devices/cpu.cpp index 7147368..eb10d74 100644 --- a/kernel/src/devices/cpu.cpp +++ b/kernel/src/devices/cpu.cpp @@ -1,64 +1,16 @@ #include "kernel/devices/cpu.hpp" -#include "kapi/acpi.hpp" #include "kapi/devices.hpp" +#include "kapi/platform.hpp" -#include #include #include #include -#include namespace kernel::devices { - namespace - { - - auto process_madt(kstd::observer_ptr madt, kapi::devices::bus & cpu) -> void - { - auto static const core_major = kapi::devices::allocate_major_number(); - auto static const lapic_major = kapi::devices::allocate_major_number(); - - auto lapic_address = madt->local_interrupt_controller_address(); - - auto const * current = reinterpret_cast(madt.get()) + sizeof(kapi::acpi::madt_header); - auto const * end = reinterpret_cast(madt.get()) + madt->length(); - - auto bsp_found = false; - auto core_index = 0; - - while (current < end) - { - auto const * sub_table = reinterpret_cast(current); - if (sub_table->type() == 0) - { - auto const * local_apic = reinterpret_cast(sub_table); - if (local_apic->flags() & 0b11) - { - auto is_bsp = !bsp_found; - bsp_found = true; - - auto apic_id = local_apic->apic_id(); - auto core = kstd::make_unique(core_major, core_index, apic_id, is_bsp); - auto lapic = kapi::acpi::create_local_interrupt_controller(lapic_major, core_index, apic_id, lapic_address); - - core->add_child(std::move(lapic)); - cpu.add_child(std::move(core)); - - ++core_index; - } - } - - current += sub_table->length(); - } - - kstd::println("[OS:DEV] Discovered {} CPU cores", core_index); - } - - } // namespace - cpu::core::core(std::size_t major_number, std::size_t minor_number, std::uint64_t hardware_id, bool is_bsp) : kapi::devices::bus{major_number, minor_number, "cpu_core"} , m_hardware_id{hardware_id} @@ -81,16 +33,12 @@ namespace kernel::devices auto cpu::probe() -> bool { - auto madt = kapi::acpi::get_table("APIC"); - if (!madt) + if (!kapi::platform::discover_cpu_topology(*this)) { - kstd::println("[OS:DEV] Failed to find ACPI APIC table"); + kstd::println("[OS:DEV] Failed to discover CPU topology"); return false; } - auto madt_header = static_cast(madt.get()); - process_madt(kstd::make_observer(madt_header), *this); - return true; } -- cgit v1.2.3 From d5c2e101d62f6b4b69c45c127e7a729d246da566 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 6 Apr 2026 19:04:16 +0200 Subject: kapi/platform: invert discovery dependencies --- kernel/kapi/platform.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'kernel') diff --git a/kernel/kapi/platform.cpp b/kernel/kapi/platform.cpp index deb72de..7638cf9 100644 --- a/kernel/kapi/platform.cpp +++ b/kernel/kapi/platform.cpp @@ -6,26 +6,21 @@ #include +#include #include #include namespace kapi::platform { - auto cpu_detected(kapi::devices::bus & bus, std::uint64_t hardware_id, bool is_bsp) -> bool + auto cpu_detected(kapi::devices::bus & bus, std::size_t major, std::size_t minor, std::uint64_t hardware_id, + bool is_bsp, kstd::unique_ptr core_interrupt_controller) -> bool { - auto static const core_major = kapi::devices::allocate_major_number(); - auto static const interrupt_controller_major = kapi::devices::allocate_major_number(); - auto static core_index = 0uz; + auto core = kstd::make_unique(major, minor, hardware_id, is_bsp); - auto core = kstd::make_unique(core_major, core_index, hardware_id, is_bsp); - auto lapic = kapi::platform::create_core_interrupt_controller(interrupt_controller_major, core_index, hardware_id); - - core->add_child(std::move(lapic)); + core->add_child(std::move(core_interrupt_controller)); bus.add_child(std::move(core)); - ++core_index; - return true; } -- cgit v1.2.3