diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-04-06 19:04:40 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-04-06 19:04:40 +0200 |
| commit | fe26083101537df306153e7bea7c291a041897f7 (patch) | |
| tree | 0f26687fb172fc1852e9c4d58c351a76e9ceb50c /kernel/kapi | |
| parent | 2a3575a267dede6a364386c0bd6edcff92421f0d (diff) | |
| parent | d5c2e101d62f6b4b69c45c127e7a729d246da566 (diff) | |
| download | teachos-fe26083101537df306153e7bea7c291a041897f7.tar.xz teachos-fe26083101537df306153e7bea7c291a041897f7.zip | |
Merge branch 'fmorgner/develop-BA-FS26/apci' into develop-BA-FS26
This patchset introduces basic support for ACPI. Currently, the only
user of that support is the CPU discovery subsystem. It uses the
processed ACPI information to initialize CPU core devices and their
associated local APICs.
Diffstat (limited to 'kernel/kapi')
| -rw-r--r-- | kernel/kapi/acpi.cpp | 174 | ||||
| -rw-r--r-- | kernel/kapi/devices.cpp | 5 | ||||
| -rw-r--r-- | kernel/kapi/devices/bus.cpp | 65 | ||||
| -rw-r--r-- | kernel/kapi/devices/device.cpp | 35 | ||||
| -rw-r--r-- | kernel/kapi/platform.cpp | 27 |
5 files changed, 306 insertions, 0 deletions
diff --git a/kernel/kapi/acpi.cpp b/kernel/kapi/acpi.cpp new file mode 100644 index 0000000..1283d7e --- /dev/null +++ b/kernel/kapi/acpi.cpp @@ -0,0 +1,174 @@ +#include "kapi/acpi.hpp" + +#include "kapi/memory.hpp" +#include "kapi/system.hpp" + +#include "kernel/acpi/manager.hpp" + +#include <kstd/memory> +#include <kstd/units> + +#include <algorithm> +#include <atomic> +#include <bit> +#include <cstddef> +#include <cstdint> +#include <optional> +#include <span> +#include <string_view> + +namespace kapi::acpi +{ + + namespace + { + auto constinit manager = std::optional<kernel::acpi::manager>{}; + } // 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<std::uint32_t>(m_rsdt_address); + return memory::physical_address{static_cast<std::uintptr_t>(raw)}; + } + + auto root_system_description_pointer::validate() const noexcept -> bool + { + return validate_checksum({reinterpret_cast<std::byte const *>(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<std::uintptr_t>(m_xsdt_address)}; + } + + auto extended_system_description_pointer::validate() const noexcept -> bool + { + return validate_checksum({reinterpret_cast<std::byte const *>(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()}; + } + + [[nodiscard]] auto madt_header::local_interrupt_controller_address() const noexcept -> memory::physical_address + { + return memory::physical_address{static_cast<std::uintptr_t>(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!"); + } + + manager.emplace(sdp); + return manager->load_tables(); + } + + auto validate_checksum(std::span<std::byte const> data) -> bool + { + auto sum = std::ranges::fold_left(data, std::uint8_t{}, [](auto acc, auto byte) { + return static_cast<std::uint8_t>(acc + static_cast<std::uint8_t>(byte)); + }); + return sum == 0; + } + + auto get_table(std::string_view signature) -> kstd::observer_ptr<system_description_table_header const> + { + return manager->get_table(signature); + } + +}; // namespace kapi::acpi diff --git a/kernel/kapi/devices.cpp b/kernel/kapi/devices.cpp index 031f2c9..dad1fe4 100644 --- a/kernel/kapi/devices.cpp +++ b/kernel/kapi/devices.cpp @@ -2,6 +2,7 @@ #include "kapi/system.hpp" +#include "kernel/devices/cpu.hpp" #include "kernel/devices/root_bus.hpp" #include <kstd/flat_map> @@ -35,6 +36,10 @@ namespace kapi::devices auto & bus = root_bus.emplace(); register_device(bus); bus.init(); + + auto cpu_major = allocate_major_number(); + auto cpu = kstd::make_unique<kernel::devices::cpu>(cpu_major); + bus.add_child(std::move(cpu)); } auto get_root_bus() -> bus & 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 <kstd/memory> +#include <kstd/print> +#include <kstd/string> +#include <kstd/vector> + +#include <algorithm> +#include <cstddef> +#include <utility> + +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<device> 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<kstd::observer_ptr<device>> 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 <kstd/string> + +#include <cstddef> + +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 diff --git a/kernel/kapi/platform.cpp b/kernel/kapi/platform.cpp new file mode 100644 index 0000000..7638cf9 --- /dev/null +++ b/kernel/kapi/platform.cpp @@ -0,0 +1,27 @@ +#include "kapi/platform.hpp" + +#include "kapi/devices.hpp" + +#include "kernel/devices/cpu.hpp" + +#include <kstd/memory> + +#include <cstddef> +#include <cstdint> +#include <utility> + +namespace kapi::platform +{ + + 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<devices::device> core_interrupt_controller) -> bool + { + auto core = kstd::make_unique<kernel::devices::cpu::core>(major, minor, hardware_id, is_bsp); + + core->add_child(std::move(core_interrupt_controller)); + bus.add_child(std::move(core)); + + return true; + } + +} // namespace kapi::platform
\ No newline at end of file |
