aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-04-06 19:04:40 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-04-06 19:04:40 +0200
commitfe26083101537df306153e7bea7c291a041897f7 (patch)
tree0f26687fb172fc1852e9c4d58c351a76e9ceb50c
parent2a3575a267dede6a364386c0bd6edcff92421f0d (diff)
parentd5c2e101d62f6b4b69c45c127e7a729d246da566 (diff)
downloadteachos-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.
-rw-r--r--.vscode/settings.json10
-rw-r--r--.vscode/tasks.json4
-rw-r--r--arch/x86_64/CMakeLists.txt4
-rw-r--r--arch/x86_64/include/arch/devices/init.hpp12
-rw-r--r--arch/x86_64/include/arch/devices/local_apic.hpp26
-rw-r--r--arch/x86_64/kapi/acpi.cpp30
-rw-r--r--arch/x86_64/kapi/devices.cpp27
-rw-r--r--arch/x86_64/kapi/platform.cpp71
-rw-r--r--arch/x86_64/src/devices/init.cpp39
-rw-r--r--arch/x86_64/src/devices/local_apic.cpp28
-rw-r--r--kapi/include/kapi/acpi.hpp134
-rw-r--r--kapi/include/kapi/devices/bus.hpp56
-rw-r--r--kapi/include/kapi/devices/device.hpp30
-rw-r--r--kapi/include/kapi/memory/layout.hpp12
-rw-r--r--kapi/include/kapi/platform.hpp34
-rw-r--r--kernel/CMakeLists.txt6
-rw-r--r--kernel/include/kernel/acpi/manager.hpp32
-rw-r--r--kernel/include/kernel/devices/cpu.hpp33
-rw-r--r--kernel/include/kernel/memory/block_list_allocator.hpp10
-rw-r--r--kernel/kapi/acpi.cpp174
-rw-r--r--kernel/kapi/devices.cpp5
-rw-r--r--kernel/kapi/devices/bus.cpp65
-rw-r--r--kernel/kapi/devices/device.cpp35
-rw-r--r--kernel/kapi/platform.cpp27
-rw-r--r--kernel/src/acpi/manager.cpp103
-rw-r--r--kernel/src/devices/cpu.cpp45
-rw-r--r--kernel/src/main.cpp10
-rw-r--r--libs/kstd/include/kstd/flat_map18
-rw-r--r--libs/kstd/include/kstd/units7
-rw-r--r--libs/multiboot2/include/multiboot2/constants/information_id.hpp8
-rw-r--r--libs/multiboot2/include/multiboot2/information.hpp43
-rw-r--r--libs/multiboot2/include/multiboot2/information/data.hpp12
32 files changed, 1043 insertions, 107 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 4271526..bebda51 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -26,12 +26,14 @@
},
"cSpell.words": [
"acpi",
+ "APIC",
"bugprone",
"cppcoreguidelines",
"crtc",
"crtp",
"efer",
"functors",
+ "hhdm",
"idtr",
"initializable",
"interprocedural",
@@ -40,9 +42,12 @@
"iwyu",
"kapi",
"kstd",
+ "lapic",
+ "madt",
"malloc",
"memcmp",
"memset",
+ "mmio",
"multiboot",
"nodiscard",
"nolintnextline",
@@ -51,12 +56,15 @@
"raii",
"rdmsr",
"RSDP",
+ "rsdt",
"rvalues",
"stringview",
"sysret",
"teachos",
"undelegated",
- "wrmsr"
+ "wrmsr",
+ "xsdp",
+ "xsdt"
],
"testMate.cpp.debug.configTemplate": {
"type": "cppdbg",
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index e07afd2..d673a7a 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -11,6 +11,8 @@
"32M",
"-machine",
"q35",
+ "-smp",
+ "4,sockets=1,cores=4,threads=1",
"-display",
"curses",
"-debugcon",
@@ -52,6 +54,8 @@
"32M",
"-machine",
"q35",
+ "-smp",
+ "4,sockets=1,cores=4,threads=1",
"-display",
"curses",
"-debugcon",
diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt
index 83cae0b..87cb98c 100644
--- a/arch/x86_64/CMakeLists.txt
+++ b/arch/x86_64/CMakeLists.txt
@@ -12,12 +12,14 @@ target_link_libraries("x86_64" PUBLIC
target_sources("x86_64" PRIVATE
# Platform-dependent KAPI implementation
+ "kapi/acpi.cpp"
"kapi/boot_modules.cpp"
"kapi/cio.cpp"
"kapi/cpu.cpp"
"kapi/devices.cpp"
"kapi/interrupts.cpp"
"kapi/memory.cpp"
+ "kapi/platform.cpp"
"kapi/system.cpp"
# CPU Initialization
@@ -38,7 +40,9 @@ target_sources("x86_64" PRIVATE
"src/debug/qemu_output.cpp"
# Devices
+ "src/devices/init.cpp"
"src/devices/legacy_pit.cpp"
+ "src/devices/local_apic.cpp"
# Memory management
"src/memory/kernel_mapper.cpp"
diff --git a/arch/x86_64/include/arch/devices/init.hpp b/arch/x86_64/include/arch/devices/init.hpp
new file mode 100644
index 0000000..c5fbf37
--- /dev/null
+++ b/arch/x86_64/include/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/include/arch/devices/local_apic.hpp b/arch/x86_64/include/arch/devices/local_apic.hpp
new file mode 100644
index 0000000..71e9758
--- /dev/null
+++ b/arch/x86_64/include/arch/devices/local_apic.hpp
@@ -0,0 +1,26 @@
+#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);
+
+ auto init() -> bool override;
+
+ private:
+ std::uint64_t m_hardware_id{};
+ kapi::memory::physical_address m_base{};
+ };
+
+} // namespace arch::devices
+
+#endif \ No newline at end of file
diff --git a/arch/x86_64/kapi/acpi.cpp b/arch/x86_64/kapi/acpi.cpp
new file mode 100644
index 0000000..ec38aee
--- /dev/null
+++ b/arch/x86_64/kapi/acpi.cpp
@@ -0,0 +1,30 @@
+#include "kapi/acpi.hpp"
+
+#include "arch/boot/boot.hpp"
+
+#include <kstd/memory>
+
+namespace kapi::acpi
+{
+
+ auto get_root_pointer() -> kstd::observer_ptr<root_system_description_pointer const>
+ {
+ auto const & mbi = kapi::boot::bootstrap_information.mbi;
+ auto system_description_pointer = static_cast<kapi::acpi::root_system_description_pointer const *>(nullptr);
+
+ if (auto const & xsdp = mbi->maybe_acpi_xsdp())
+ {
+ auto data = xsdp->pointer().data();
+
+ system_description_pointer = reinterpret_cast<kapi::acpi::root_system_description_pointer const *>(data);
+ }
+ else if (auto const & rsdp = mbi->maybe_acpi_rsdp())
+ {
+ auto data = rsdp->pointer().data();
+ system_description_pointer = reinterpret_cast<kapi::acpi::root_system_description_pointer const *>(data);
+ }
+
+ return kstd::make_observer(system_description_pointer);
+ }
+
+} // namespace kapi::acpi \ No newline at end of file
diff --git a/arch/x86_64/kapi/devices.cpp b/arch/x86_64/kapi/devices.cpp
index b15503d..47c7f8c 100644
--- a/arch/x86_64/kapi/devices.cpp
+++ b/arch/x86_64/kapi/devices.cpp
@@ -1,35 +1,14 @@
#include "kapi/devices.hpp"
-#include "arch/bus/isa.hpp"
-#include "arch/devices/legacy_pit.hpp"
-
-#include <kstd/memory>
-#include <kstd/print>
-
-#include <cstdint>
-#include <utility>
+#include "arch/devices/init.hpp"
namespace kapi::devices
{
- namespace
- {
- constexpr auto pit_frequency_in_hz = std::uint32_t{100u};
- }
-
auto init_platform_devices() -> void
{
- kstd::println("[x86_64:devices] 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 = get_root_bus();
- root_bus.add_child(std::move(isa_bus));
+ 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/platform.cpp b/arch/x86_64/kapi/platform.cpp
new file mode 100644
index 0000000..380fc66
--- /dev/null
+++ b/arch/x86_64/kapi/platform.cpp
@@ -0,0 +1,71 @@
+#include "kapi/platform.hpp"
+
+#include "kapi/acpi.hpp"
+#include "kapi/devices.hpp"
+#include "kapi/memory.hpp"
+
+#include "arch/devices/local_apic.hpp"
+
+#include <kstd/memory>
+#include <kstd/print>
+
+#include <cstddef>
+#include <utility>
+
+namespace kapi::platform
+{
+
+ namespace
+ {
+ constexpr auto default_lapic_address = kapi::memory::physical_address{0xFEE0'0000};
+ }
+
+ auto discover_cpu_topology(kapi::devices::bus & bus) -> 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 madt = kapi::acpi::get_table("APIC");
+ if (!madt)
+ {
+ kstd::println("[x86_64:PLT] Failed to find ACPI APIC table");
+ return false;
+ }
+
+ auto const * current = reinterpret_cast<std::byte const *>(madt.get()) + sizeof(kapi::acpi::madt_header);
+ auto const * end = reinterpret_cast<std::byte const *>(madt.get()) + madt->length();
+
+ auto bsp_found = false;
+ auto core_count = 0uz;
+
+ while (current < end)
+ {
+ auto const * sub_table = reinterpret_cast<kapi::acpi::madt_subtable_header const *>(current);
+ if (sub_table->type() == 0)
+ {
+ auto const * local_apic = reinterpret_cast<kapi::acpi::madt_local_apic const *>(sub_table);
+ if (local_apic->flags() & 0b11)
+ {
+ auto is_bsp = !bsp_found;
+ bsp_found = true;
+
+ auto lapic = kstd::make_unique<arch::devices::local_apic>(interrupt_controller_major, core_index,
+ local_apic->apic_id(), default_lapic_address);
+ if (kapi::platform::cpu_detected(bus, core_major, core_index, local_apic->processor_id(), is_bsp,
+ std::move(lapic)))
+ {
+ ++core_count;
+ }
+ }
+ }
+
+ current += sub_table->length();
+ }
+
+ kstd::println("[x86_64:PLT] Found {} CPU cores", core_count);
+
+ return core_count > 0;
+ }
+
+} // namespace kapi::platform \ No newline at end of file
diff --git a/arch/x86_64/src/devices/init.cpp b/arch/x86_64/src/devices/init.cpp
new file mode 100644
index 0000000..6cba986
--- /dev/null
+++ b/arch/x86_64/src/devices/init.cpp
@@ -0,0 +1,39 @@
+#include "arch/devices/init.hpp"
+
+#include "kapi/devices.hpp"
+
+#include "arch/bus/isa.hpp"
+#include "arch/devices/legacy_pit.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 init_acpi_devices() -> void {}
+
+ 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/src/devices/local_apic.cpp b/arch/x86_64/src/devices/local_apic.cpp
new file mode 100644
index 0000000..beb75ef
--- /dev/null
+++ b/arch/x86_64/src/devices/local_apic.cpp
@@ -0,0 +1,28 @@
+#include "arch/devices/local_apic.hpp"
+
+#include "kapi/devices.hpp"
+#include "kapi/memory.hpp"
+
+#include <kstd/print>
+
+#include <cstddef>
+#include <cstdint>
+
+namespace arch::devices
+{
+
+ local_apic::local_apic(std::size_t major, std::size_t minor, std::uint64_t hardware_id,
+ kapi::memory::physical_address base)
+ : kapi::devices::device{major, minor, "lapic"}
+ , m_hardware_id{hardware_id}
+ , m_base{base}
+ {}
+
+ auto local_apic::init() -> bool
+ {
+ kstd::println("[x86_64:DEV] Initializing local APIC on core {}", m_hardware_id);
+
+ return true;
+ }
+
+} // namespace arch::devices \ No newline at end of file
diff --git a/kapi/include/kapi/acpi.hpp b/kapi/include/kapi/acpi.hpp
new file mode 100644
index 0000000..75b6c48
--- /dev/null
+++ b/kapi/include/kapi/acpi.hpp
@@ -0,0 +1,134 @@
+#ifndef TEACHOS_KAPI_ACPI_HPP
+#define TEACHOS_KAPI_ACPI_HPP
+
+#include "kapi/memory.hpp"
+
+#include <kstd/memory>
+#include <kstd/units>
+
+#include <array>
+#include <cstddef>
+#include <cstdint>
+#include <span>
+#include <string_view>
+
+namespace kapi::acpi
+{
+
+ //! @addtogroup kapi-acpi-kernel-defined
+ //! @{
+
+ struct [[gnu::packed]] root_system_description_pointer
+ {
+ [[nodiscard]] auto oem_id() const noexcept -> std::string_view;
+ [[nodiscard]] auto revision() const noexcept -> std::uint8_t;
+ [[nodiscard]] auto signature() const noexcept -> std::string_view;
+ [[nodiscard]] auto table_address() const noexcept -> memory::physical_address;
+ [[nodiscard]] auto validate() const noexcept -> bool;
+
+ private:
+ std::array<char, 8> m_signature;
+ [[maybe_unused]] std::uint8_t m_checksum;
+ std::array<char, 6> m_oem_id;
+ std::uint8_t m_revision;
+ std::array<std::byte, 4> m_rsdt_address;
+ };
+
+ struct [[gnu::packed]] extended_system_description_pointer : root_system_description_pointer
+ {
+ [[nodiscard]] auto length() const noexcept -> kstd::units::bytes;
+ [[nodiscard]] auto table_address() const noexcept -> memory::physical_address;
+ [[nodiscard]] auto validate() const noexcept -> bool;
+
+ private:
+ std::uint32_t m_length;
+ std::array<std::byte, 8> m_xsdt_address;
+ [[maybe_unused]] std::uint8_t m_extended_checksum;
+ [[maybe_unused]] std::array<std::byte, 3> m_reserved;
+ };
+
+ struct [[gnu::packed]] system_description_table_header
+ {
+ [[nodiscard]] auto checksum() const noexcept -> std::uint8_t;
+ [[nodiscard]] auto creator_revision() const noexcept -> std::uint32_t;
+ [[nodiscard]] auto creator_id() const noexcept -> std::uint32_t;
+ [[nodiscard]] auto length() const noexcept -> kstd::units::bytes;
+ [[nodiscard]] auto oem_id() const noexcept -> std::string_view;
+ [[nodiscard]] auto oem_revision() const noexcept -> std::uint32_t;
+ [[nodiscard]] auto oem_table_id() const noexcept -> std::string_view;
+ [[nodiscard]] auto revision() const noexcept -> std::uint8_t;
+ [[nodiscard]] auto signature() const noexcept -> std::string_view;
+
+ private:
+ std::array<char, 4> m_signature;
+ std::uint32_t m_length;
+ std::uint8_t m_revision;
+ std::uint8_t m_checksum;
+ std::array<char, 6> m_oem_id;
+ std::array<char, 8> m_oem_table_id;
+ std::uint32_t m_oem_revision;
+ std::uint32_t m_creator_id;
+ std::uint32_t m_creator_revision;
+ };
+
+ struct [[gnu::packed]] madt_header : system_description_table_header
+ {
+ [[nodiscard]] auto local_interrupt_controller_address() const noexcept -> memory::physical_address;
+ [[nodiscard]] auto flags() const noexcept -> std::uint32_t;
+
+ private:
+ std::uint32_t m_local_interrupt_controller_address;
+ std::uint32_t m_flags;
+ };
+
+ struct [[gnu::packed]] madt_subtable_header
+ {
+ [[nodiscard]] auto type() const noexcept -> std::uint8_t;
+ [[nodiscard]] auto length() const noexcept -> std::size_t;
+
+ private:
+ std::uint8_t m_type;
+ std::uint8_t m_length;
+ };
+
+ struct [[gnu::packed]] madt_local_apic : madt_subtable_header
+ {
+ [[nodiscard]] auto apic_id() const noexcept -> std::uint8_t;
+ [[nodiscard]] auto flags() const noexcept -> std::uint32_t;
+ [[nodiscard]] auto processor_id() const noexcept -> std::uint32_t;
+
+ private:
+ std::uint8_t m_processor_id;
+ std::uint8_t m_apic_id;
+ std::uint32_t m_flags;
+ };
+
+ //! Initialize the ACPI subsystem and discover the available tables.
+ //!
+ //! @return true iff. a valid system description tabled was found, false otherwise.
+ auto init(root_system_description_pointer const & sdp) -> bool;
+
+ //! Validate and ACPI entity checksum.
+ //!
+ //! @param data The data to validate the checksum of.
+ //! @return true iff. the checksum is valid, false otherwise.
+ auto validate_checksum(std::span<std::byte const> data) -> bool;
+
+ //! Get an ACPI table by its signature.
+ //!
+ //! @param signature The signature of the table to get.
+ //! @return A pointer to the table if found, nullptr otherwise.
+ auto get_table(std::string_view signature) -> kstd::observer_ptr<system_description_table_header const>;
+
+ //! @}
+
+ //! @addtogroup kapi-acpi-platform-defined
+ //! @{
+
+ auto get_root_pointer() -> kstd::observer_ptr<root_system_description_pointer const>;
+
+ //! @}
+
+} // namespace kapi::acpi
+
+#endif
diff --git a/kapi/include/kapi/devices/bus.hpp b/kapi/include/kapi/devices/bus.hpp
index 052c062..7b2d41f 100644
--- a/kapi/include/kapi/devices/bus.hpp
+++ b/kapi/include/kapi/devices/bus.hpp
@@ -1,24 +1,22 @@
#ifndef TEACHOS_KAPI_DEVICES_BUS_HPP
#define TEACHOS_KAPI_DEVICES_BUS_HPP
+// IWYU pragma: private, include "kapi/devices.hpp"
+
#include "kapi/devices/device.hpp"
-#include "kapi/devices/manager.hpp"
-#include "kapi/system.hpp"
#include <kstd/memory>
#include <kstd/print>
#include <kstd/string>
#include <kstd/vector>
-#include <algorithm>
#include <atomic>
#include <cstddef>
-#include <utility>
namespace kapi::devices
{
- //! @addtogroup kapi-devices
+ //! @addtogroup kapi-devices-kernel-defined
//! @{
//! A bus device that represents a logical/physical tree of devices and busses.
@@ -29,65 +27,27 @@ namespace kapi::devices
//! @param major The major number of the bus.
//! @param minor The minor number of the bus.
//! @param name The name of the bus.
- bus(std::size_t major, std::size_t minor, kstd::string const & name)
- : device(major, minor, name)
- {}
+ bus(std::size_t major, std::size_t minor, kstd::string const & name);
//! Initialize the bus and all of its children.
//!
//! @return true iff. the bus and all of its children are healthy, false otherwise.
- auto init() -> bool final
- {
- 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("[kAPI:BUS] Initializing child device {}@{}", child->name(), name());
- return child->init() && acc;
- });
- }
+ auto init() -> bool final;
//! Attach a child device to this bus.
//!
//! Whenever a device is attached to a bus, the bus takes sole ownership of the device.
//!
//! @param child The child device to attach.
- auto 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("[kAPI:BUS] Initializing child device {}@{}", observer->name(), name());
- if (!observer->init())
- {
- kapi::system::panic("[kAPI:BUS] Failed to initialize child device");
- }
- }
- }
+ auto add_child(kstd::unique_ptr<device> child) -> void;
- [[nodiscard]] auto children() const -> kstd::vector<kstd::observer_ptr<device>> const &
- {
- return m_observers;
- }
+ [[nodiscard]] auto children() const -> kstd::vector<kstd::observer_ptr<device>> const &;
protected:
//! Probe the bus hardware state.
//!
//! @return true iff. the bus hardware is healthy, false otherwise.
- auto virtual probe() -> bool
- {
- return true;
- }
+ auto virtual probe() -> bool;
private:
kstd::vector<kstd::unique_ptr<device>> m_devices;
diff --git a/kapi/include/kapi/devices/device.hpp b/kapi/include/kapi/devices/device.hpp
index b7b6bba..b3647da 100644
--- a/kapi/include/kapi/devices/device.hpp
+++ b/kapi/include/kapi/devices/device.hpp
@@ -1,6 +1,8 @@
#ifndef TEACH_OS_KAPI_DEVICES_DEVICE_HPP
#define TEACH_OS_KAPI_DEVICES_DEVICE_HPP
+// IWYU pragma: private, include "kapi/devices.hpp"
+
#include <kstd/string>
#include <cstddef>
@@ -8,7 +10,7 @@
namespace kapi::devices
{
- //! @addtogroup kapi-devices
+ //! @addtogroup kapi-devices-kernel-defined
//! @{
/**
@@ -22,11 +24,7 @@ namespace kapi::devices
* @param minor Device minor number.
* @param name Device name.
*/
- device(size_t major, size_t minor, kstd::string const & name)
- : m_major(major)
- , m_minor(minor)
- , m_name(name)
- {}
+ device(size_t major, size_t minor, kstd::string const & name);
/**
* @brief Virtual destructor for device.
@@ -43,37 +41,25 @@ namespace kapi::devices
* @brief Returns the major number of the device.
* @return Device major number.
*/
- [[nodiscard]] auto major() const -> size_t
- {
- return m_major;
- }
+ [[nodiscard]] auto major() const -> size_t;
/**
* @brief Returns the minor number of the device.
* @return Device minor number.
*/
- [[nodiscard]] auto minor() const -> size_t
- {
- return m_minor;
- }
+ [[nodiscard]] auto minor() const -> size_t;
/**
* @brief Returns the name of the device.
* @return Device name.
*/
- [[nodiscard]] auto name() const -> kstd::string const &
- {
- return m_name;
- }
+ [[nodiscard]] auto name() const -> kstd::string const &;
/**
* @brief Check if the device is a block device.
* @return true if this device is a block device, false otherwise.
*/
- [[nodiscard]] virtual auto is_block_device() const -> bool
- {
- return false;
- }
+ [[nodiscard]] virtual auto is_block_device() const -> bool;
private:
size_t m_major;
diff --git a/kapi/include/kapi/memory/layout.hpp b/kapi/include/kapi/memory/layout.hpp
index 157f41e..26b48d8 100644
--- a/kapi/include/kapi/memory/layout.hpp
+++ b/kapi/include/kapi/memory/layout.hpp
@@ -37,6 +37,18 @@ namespace kapi::memory
//! The linear base address of the loaded kernel image.
constexpr auto kernel_base = linear_address{0xffff'ffff'8000'0000uz};
+ //! Convert a physical address to a linear address using the higher-half direct map.
+ constexpr auto hhdm_to_linear(physical_address address) -> linear_address
+ {
+ return linear_address{address.raw() + higher_half_direct_map_base.raw()};
+ }
+
+ //! Convert a linear address in the higher-half direct map to a physical address.
+ constexpr auto hhdm_to_physical(linear_address address) -> physical_address
+ {
+ return physical_address{address.raw() - higher_half_direct_map_base.raw()};
+ }
+
} // namespace kapi::memory
#endif \ No newline at end of file
diff --git a/kapi/include/kapi/platform.hpp b/kapi/include/kapi/platform.hpp
new file mode 100644
index 0000000..e1e267e
--- /dev/null
+++ b/kapi/include/kapi/platform.hpp
@@ -0,0 +1,34 @@
+#ifndef TEACHOS_KAPI_PLATFORM_HPP
+#define TEACHOS_KAPI_PLATFORM_HPP
+
+#include "kapi/devices.hpp"
+
+#include <kstd/memory>
+
+#include <cstddef>
+#include <cstdint>
+
+namespace kapi::platform
+{
+
+ //! @addtogroup kapi-platform-kernel-defined
+ //! @{
+
+ 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;
+ //! @}
+
+ //! @addtogroup kapi-platform-platform-defined
+ //! @{
+
+ //! Discover the CPU topology of the platform and attach it to the given CPU bus.
+ //!
+ //! @param bus The bus to attach the CPU topology to.
+ //! @return true iff. the CPU topology was discovered successfully, false otherwise.
+ auto discover_cpu_topology(kapi::devices::bus & bus) -> bool;
+
+ //! @}
+
+} // namespace kapi::platform
+
+#endif \ No newline at end of file
diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt
index 9868eb9..22513ea 100644
--- a/kernel/CMakeLists.txt
+++ b/kernel/CMakeLists.txt
@@ -1,11 +1,15 @@
add_library("kernel_objs" OBJECT
# Platform-independent KAPI implementation
+ "kapi/acpi.cpp"
"kapi/boot_modules.cpp"
"kapi/cio.cpp"
"kapi/cpu.cpp"
"kapi/devices.cpp"
+ "kapi/devices/bus.cpp"
+ "kapi/devices/device.cpp"
"kapi/interrupts.cpp"
"kapi/memory.cpp"
+ "kapi/platform.cpp"
"kapi/system.cpp"
# KSTD OS Implementation
@@ -13,11 +17,13 @@ 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"
"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
new file mode 100644
index 0000000..fae59a6
--- /dev/null
+++ b/kernel/include/kernel/acpi/manager.hpp
@@ -0,0 +1,32 @@
+#ifndef TEACHOS_KERNEL_ACPI_MANAGER_HPP
+#define TEACHOS_KERNEL_ACPI_MANAGER_HPP
+
+#include "kapi/acpi.hpp"
+
+#include <kstd/flat_map>
+#include <kstd/memory>
+#include <kstd/vector>
+