aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-04-16 10:03:35 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-04-16 10:03:35 +0200
commit776ab2749d5af0a34fd2aa6103a377ddc04d4c53 (patch)
tree06b094e66f1a15a4282fc6294ab5d4751b792754
parent28cae58fe117e5fcfc46fd6378e19387cd73b2fe (diff)
downloadteachos-776ab2749d5af0a34fd2aa6103a377ddc04d4c53.tar.xz
teachos-776ab2749d5af0a34fd2aa6103a377ddc04d4c53.zip
acpi: introduce XSDT type
-rw-r--r--arch/x86_64/kapi/cpu.cpp16
-rw-r--r--kernel/src/acpi/manager.cpp44
-rw-r--r--libs/acpi/CMakeLists.txt3
-rw-r--r--libs/acpi/acpi/acpi.hpp1
-rw-r--r--libs/acpi/acpi/data/rsdt.hpp1
-rw-r--r--libs/acpi/acpi/data/xsdt.cpp38
-rw-r--r--libs/acpi/acpi/data/xsdt.hpp42
-rw-r--r--libs/acpi/acpi/data/xsdt.test.cpp46
-rw-r--r--libs/acpi/test_data/basic_xsdt.asl26
-rw-r--r--libs/acpi/test_data/tables.S1
-rw-r--r--libs/acpi/test_data/tables.hpp1
11 files changed, 187 insertions, 32 deletions
diff --git a/arch/x86_64/kapi/cpu.cpp b/arch/x86_64/kapi/cpu.cpp
index 22936c2..965998c 100644
--- a/arch/x86_64/kapi/cpu.cpp
+++ b/arch/x86_64/kapi/cpu.cpp
@@ -23,8 +23,8 @@ namespace kapi::cpu
namespace
{
- constexpr auto candidate_flags = ::acpi::processor_local_apic::flags::processor_enabled //
- | ::acpi::processor_local_apic::flags::online_capable;
+ constexpr auto candidate_flags = ::acpi::processor_local_apic_entry::flags::processor_enabled //
+ | ::acpi::processor_local_apic_entry::flags::online_capable;
}
auto init() -> void
@@ -52,7 +52,7 @@ namespace kapi::cpu
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::madt_table_signature>();
+ 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");
@@ -62,10 +62,8 @@ namespace kapi::cpu
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 const &>(entry);
- }) | std::views::filter([](auto const & entry) {
- return static_cast<bool>(entry.active_flags() & candidate_flags);
- });
+ 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;
@@ -77,8 +75,8 @@ namespace kapi::cpu
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.apic_id(), local_apic_address, 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;
}
diff --git a/kernel/src/acpi/manager.cpp b/kernel/src/acpi/manager.cpp
index 2f2a1bd..5876799 100644
--- a/kernel/src/acpi/manager.cpp
+++ b/kernel/src/acpi/manager.cpp
@@ -8,8 +8,10 @@
#include <acpi/acpi.hpp>
+#include <algorithm>
#include <cstddef>
#include <cstdint>
+#include <ranges>
#include <string_view>
namespace kernel::acpi
@@ -32,7 +34,7 @@ namespace kernel::acpi
}
auto physical_extended_table_address = kapi::memory::physical_address{xsdp->table_address()};
auto linear_extended_table_address = kapi::memory::hhdm_to_linear(physical_extended_table_address);
- m_rsdt = static_cast<::acpi::table_header const *>(linear_extended_table_address);
+ m_rsdt = static_cast<::acpi::xsdt const *>(linear_extended_table_address);
m_extended = true;
}
else
@@ -54,29 +56,12 @@ namespace kernel::acpi
kapi::system::panic("[OS:ACPI] Invalid RSDT checksum!");
}
- auto entry_size = m_extended ? sizeof(std::uint64_t) : sizeof(std::uint32_t);
- auto entry_count = (m_rsdt->length().value - sizeof(::acpi::table_header)) / entry_size;
- auto entries_base = reinterpret_cast<std::byte const *>(m_rsdt) + sizeof(::acpi::table_header);
+ auto check_and_register_table = [&](auto table_address) -> void {
+ auto physical_table_address = kapi::memory::physical_address{reinterpret_cast<std::uintptr_t>(table_address)};
+ auto mapped_table = kapi::memory::hhdm_to_linear(physical_table_address);
+ auto table = static_cast<::acpi::table_header const *>(mapped_table);
- 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<std::uint64_t const *>(entries_base + (i * entry_size));
- physical_table_address = kapi::memory::physical_address{*entry};
- }
- else
- {
- auto entry = reinterpret_cast<std::uint32_t const *>(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<::acpi::table_header const *>(linear_table_address);
-
- if (!::acpi::validate_checksum({reinterpret_cast<std::byte const *>(table), table->length().value}))
+ if (!::acpi::validate_checksum({static_cast<std::byte const *>(mapped_table), table->length().value}))
{
kstd::println(kstd::print_sink::stderr, "[OS:ACPI] Invalid table checksum!");
}
@@ -85,6 +70,19 @@ namespace kernel::acpi
kstd::println("[OS:ACPI] Found '{}' ACPI table", table->signature());
m_tables.emplace(table->signature(), table);
}
+ };
+
+ if (m_extended)
+ {
+ auto xsdt = static_cast<::acpi::xsdt const *>(m_rsdt);
+ std::ranges::for_each(*xsdt | std::views::transform([](auto const & entry) { return entry.address(); }),
+ check_and_register_table);
+ }
+ else
+ {
+ auto rsdt = static_cast<::acpi::rsdt const *>(m_rsdt);
+ std::ranges::for_each(*rsdt | std::views::transform([](auto const & entry) { return entry.address(); }),
+ check_and_register_table);
}
return !m_tables.empty();
diff --git a/libs/acpi/CMakeLists.txt b/libs/acpi/CMakeLists.txt
index 833dcea..55d5b54 100644
--- a/libs/acpi/CMakeLists.txt
+++ b/libs/acpi/CMakeLists.txt
@@ -23,6 +23,7 @@ target_sources("acpi" PRIVATE
"acpi/common/table_header.cpp"
"acpi/data/madt.cpp"
"acpi/data/rsdt.cpp"
+ "acpi/data/xsdt.cpp"
"acpi/pointers.cpp"
)
@@ -44,6 +45,7 @@ if(NOT CMAKE_CROSSCOMPILING)
"basic_madt"
"basic_rsdt"
"basic_rsdp"
+ "basic_xsdt"
"table_header"
)
@@ -63,6 +65,7 @@ if(NOT CMAKE_CROSSCOMPILING)
"acpi/common/table_header.test.cpp"
"acpi/data/madt.test.cpp"
"acpi/data/rsdt.test.cpp"
+ "acpi/data/xsdt.test.cpp"
"acpi/pointers.test.cpp"
"test_data/tables.S"
diff --git a/libs/acpi/acpi/acpi.hpp b/libs/acpi/acpi/acpi.hpp
index 385ddc9..0da44a8 100644
--- a/libs/acpi/acpi/acpi.hpp
+++ b/libs/acpi/acpi/acpi.hpp
@@ -6,6 +6,7 @@
#include <acpi/common/table_type.hpp> // IWYU pragma: export
#include <acpi/data/madt.hpp> // IWYU pragma: export
#include <acpi/data/rsdt.hpp> // IWYU pragma: export
+#include <acpi/data/xsdt.hpp> // IWYU pragma: export
#include <acpi/pointers.hpp> // IWYU pragma: export
#endif
diff --git a/libs/acpi/acpi/data/rsdt.hpp b/libs/acpi/acpi/data/rsdt.hpp
index 88c5fd1..a661187 100644
--- a/libs/acpi/acpi/data/rsdt.hpp
+++ b/libs/acpi/acpi/data/rsdt.hpp
@@ -1,6 +1,7 @@
#ifndef ACPI_DATA_RSDT_HPP
#define ACPI_DATA_RSDT_HPP
+#include <acpi/common/table_header.hpp>
#include <acpi/common/table_signature.hpp>
#include <acpi/common/table_type.hpp>
#include <acpi/common/vla_table.hpp>
diff --git a/libs/acpi/acpi/data/xsdt.cpp b/libs/acpi/acpi/data/xsdt.cpp
new file mode 100644
index 0000000..b4202b8
--- /dev/null
+++ b/libs/acpi/acpi/data/xsdt.cpp
@@ -0,0 +1,38 @@
+#include <kstd/cstring>
+
+#include <acpi/common/table_header.hpp>
+#include <acpi/data/xsdt.hpp>
+
+#include <cstddef>
+#include <cstdint>
+#include <span>
+
+namespace acpi
+{
+
+ struct xsdt_entry_data
+ {
+ std::uint64_t address;
+ };
+
+ [[nodiscard]] auto xsdt_entry::address() const noexcept -> table_header *
+ {
+ using type = decltype(xsdt_entry_data::address);
+
+ constexpr auto size = sizeof(type);
+ constexpr auto offset = offsetof(xsdt_entry_data, address);
+
+ auto const data = std::span<std::byte const, size>{m_data.data() + offset, size};
+ auto value = type{};
+
+ kstd::libc::memcpy(&value, data.data(), size);
+
+ return reinterpret_cast<table_header *>(static_cast<uintptr_t>(value));
+ }
+
+ [[nodiscard]] auto xsdt_entry::length() const noexcept -> std::size_t
+ {
+ return sizeof(m_data);
+ }
+
+} // namespace acpi \ No newline at end of file
diff --git a/libs/acpi/acpi/data/xsdt.hpp b/libs/acpi/acpi/data/xsdt.hpp
new file mode 100644
index 0000000..965f23c
--- /dev/null
+++ b/libs/acpi/acpi/data/xsdt.hpp
@@ -0,0 +1,42 @@
+#ifndef ACPI_DATA_XSDT_HPP
+#define ACPI_DATA_XSDT_HPP
+
+#include <acpi/common/table_header.hpp>
+#include <acpi/common/table_signature.hpp>
+#include <acpi/common/table_type.hpp>
+#include <acpi/common/vla_table.hpp>
+
+#include <array>
+#include <cstddef>
+
+namespace acpi
+{
+
+ template<>
+ struct table_signature<struct xsdt>
+ {
+ constexpr char static const value[] = "XSDT"; // NOLINT
+ };
+
+ template<>
+ struct table_type<table_signature_v<struct xsdt>>
+ {
+ using type = struct xsdt;
+ };
+
+ struct xsdt_entry
+ {
+ [[nodiscard]] auto address() const noexcept -> table_header *;
+ [[nodiscard]] auto length() const noexcept -> std::size_t;
+
+ private:
+ std::array<std::byte, 8> m_data{};
+ };
+
+ struct xsdt : vla_table<xsdt_entry, xsdt>
+ {
+ };
+
+} // namespace acpi
+
+#endif \ No newline at end of file
diff --git a/libs/acpi/acpi/data/xsdt.test.cpp b/libs/acpi/acpi/data/xsdt.test.cpp
new file mode 100644
index 0000000..7fb564c
--- /dev/null
+++ b/libs/acpi/acpi/data/xsdt.test.cpp
@@ -0,0 +1,46 @@
+#include <kstd/units>
+
+#include <acpi/acpi.hpp>
+#include <acpi/data/xsdt.hpp>
+#include <catch2/catch_test_macros.hpp>
+#include <test_data/tables.hpp>
+
+#include <iterator>
+
+SCENARIO("XSDT parsing", "[xsdt]")
+{
+ GIVEN("The basic compiled XSDT containing 8 table pointers")
+ {
+ auto data = acpi::test_data::tables::basic_xsdt();
+
+ WHEN("parsing the table")
+ {
+ auto xsdt = reinterpret_cast<acpi::xsdt const *>(data.data());
+
+ THEN("the signature is correct")
+ {
+ REQUIRE(xsdt->signature() == "XSDT");
+ }
+
+ THEN("validate returns true")
+ {
+ REQUIRE(xsdt->validate());
+ }
+
+ THEN("there are 8 entries in the table")
+ {
+ REQUIRE(std::distance(xsdt->begin(), xsdt->end()) == 8);
+ }
+
+ THEN("the first entry has address 0x10")
+ {
+ REQUIRE(xsdt->cbegin()->address() == reinterpret_cast<acpi::table_header *>(0x10));
+ }
+
+ THEN("the length is sizeof(xsdt) + 8 * sizeof(xsdt_entry)")
+ {
+ REQUIRE(xsdt->length().value == sizeof(acpi::xsdt) + 8 * sizeof(acpi::xsdt_entry));
+ }
+ }
+ }
+}
diff --git a/libs/acpi/test_data/basic_xsdt.asl b/libs/acpi/test_data/basic_xsdt.asl
new file mode 100644
index 0000000..d8589f9
--- /dev/null
+++ b/libs/acpi/test_data/basic_xsdt.asl
@@ -0,0 +1,26 @@
+/*
+ * Intel ACPI Component Architecture
+ * iASL Compiler/Disassembler version 20251212 (64-bit version)
+ * Copyright (c) 2000 - 2025 Intel Corporation
+ *
+ * Template for [XSDT] ACPI Table (static data table)
+ * Format: [ByteLength] FieldName : HexFieldValue
+ */
+[0004] Signature : "XSDT" [Extended System Description Table]
+[0004] Table Length : 00000064
+[0001] Revision : 01
+[0001] Checksum : 8B
+[0006] Oem ID : "INTEL "
+[0008] Oem Table ID : "TEMPLATE"
+[0004] Oem Revision : 00000001
+[0004] Asl Compiler ID : "INTL"
+[0004] Asl Compiler Revision : 20100528
+
+[0008] ACPI Table Address 0 : 0000000000000010
+[0008] ACPI Table Address 1 : 0000000000000020
+[0008] ACPI Table Address 2 : 0000000000000030
+[0008] ACPI Table Address 3 : 0000000000000040
+[0008] ACPI Table Address 4 : 0000000000000050
+[0008] ACPI Table Address 5 : 0000000000000060
+[0008] ACPI Table Address 6 : 0000000000000070
+[0008] ACPI Table Address 7 : 0000000000000080
diff --git a/libs/acpi/test_data/tables.S b/libs/acpi/test_data/tables.S
index da9a12f..641db6a 100644
--- a/libs/acpi/test_data/tables.S
+++ b/libs/acpi/test_data/tables.S
@@ -11,6 +11,7 @@
TABLE(basic_madt, "basic_madt.aml")
TABLE(basic_rsdt, "basic_rsdt.aml")
TABLE(basic_rsdp, "basic_rsdp.aml")
+TABLE(basic_xsdt, "basic_xsdt.aml")
TABLE(table_header, "table_header.aml")
#undef TABLE
diff --git a/libs/acpi/test_data/tables.hpp b/libs/acpi/test_data/tables.hpp
index dc39b37..e91f1a5 100644
--- a/libs/acpi/test_data/tables.hpp
+++ b/libs/acpi/test_data/tables.hpp
@@ -18,6 +18,7 @@ namespace acpi::test_data::tables
TABLE(basic_madt);
TABLE(basic_rsdt);
TABLE(basic_rsdp);
+ TABLE(basic_xsdt);
TABLE(table_header);
} // namespace acpi::test_data::tables