From 89f1c730fb9daf4a5da0748934ca5befd90eb731 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 16 Apr 2026 09:28:16 +0200 Subject: acpi: move madt to data --- libs/acpi/CMakeLists.txt | 4 +- libs/acpi/acpi/acpi.hpp | 2 +- libs/acpi/acpi/data/madt.cpp | 112 ++++++++++++++++++++++++++++++++++++ libs/acpi/acpi/data/madt.hpp | 117 ++++++++++++++++++++++++++++++++++++++ libs/acpi/acpi/data/madt.test.cpp | 55 ++++++++++++++++++ libs/acpi/acpi/madt.cpp | 112 ------------------------------------ libs/acpi/acpi/madt.hpp | 117 -------------------------------------- libs/acpi/acpi/madt.test.cpp | 55 ------------------ 8 files changed, 287 insertions(+), 287 deletions(-) create mode 100644 libs/acpi/acpi/data/madt.cpp create mode 100644 libs/acpi/acpi/data/madt.hpp create mode 100644 libs/acpi/acpi/data/madt.test.cpp delete mode 100644 libs/acpi/acpi/madt.cpp delete mode 100644 libs/acpi/acpi/madt.hpp delete mode 100644 libs/acpi/acpi/madt.test.cpp diff --git a/libs/acpi/CMakeLists.txt b/libs/acpi/CMakeLists.txt index 97c351b..f6e484c 100644 --- a/libs/acpi/CMakeLists.txt +++ b/libs/acpi/CMakeLists.txt @@ -21,7 +21,7 @@ file(GLOB_RECURSE ACPI_HEADERS target_sources("acpi" PRIVATE "acpi/common/checksum.cpp" "acpi/common/table_header.cpp" - "acpi/madt.cpp" + "acpi/data/madt.cpp" "acpi/pointers.cpp" ) @@ -60,7 +60,7 @@ if(NOT CMAKE_CROSSCOMPILING) add_executable("acpi_tests" "acpi/common/table_header.test.cpp" - "acpi/madt.test.cpp" + "acpi/data/madt.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 2962c7a..4cfcede 100644 --- a/libs/acpi/acpi/acpi.hpp +++ b/libs/acpi/acpi/acpi.hpp @@ -4,7 +4,7 @@ #include // IWYU pragma: export #include // IWYU pragma: export #include // IWYU pragma: export -#include // IWYU pragma: export +#include // IWYU pragma: export #include // IWYU pragma: export #endif diff --git a/libs/acpi/acpi/data/madt.cpp b/libs/acpi/acpi/data/madt.cpp new file mode 100644 index 0000000..a8d4741 --- /dev/null +++ b/libs/acpi/acpi/data/madt.cpp @@ -0,0 +1,112 @@ +#include + +#include + +#include +#include +#include +#include + +namespace acpi +{ + + struct madt_data + { + std::uint32_t local_interrupt_controller_address; + std::uint32_t flags; + }; + + static_assert(sizeof(madt_data) == 8); + + auto madt::local_interrupt_controller_address() const noexcept -> std::uintptr_t + { + using type = decltype(madt_data::local_interrupt_controller_address); + + constexpr auto size = sizeof(type); + constexpr auto offset = offsetof(madt_data, local_interrupt_controller_address); + + auto const data = std::span{m_data.data() + offset, size}; + auto value = type{}; + + kstd::libc::memcpy(&value, data.data(), size); + + return value; + } + + auto madt::flags() const noexcept -> std::uint32_t + { + using type = decltype(madt_data::flags); + + constexpr auto size = sizeof(type); + constexpr auto offset = offsetof(madt_data, flags); + + auto const data = std::span{m_data.data() + offset, size}; + auto value = type{}; + + kstd::libc::memcpy(&value, data.data(), size); + + return value; + } + + struct madt_entry_data + { + std::uint8_t type; + std::uint8_t length; + }; + + static_assert(sizeof(madt_entry_data) == 2); + + auto madt_entry::type() const noexcept -> enum type + { + constexpr auto field_offset = offsetof(madt_entry_data, type); + + return std::bit_cast(*(m_data.data() + field_offset)); + } + + auto madt_entry::length() const noexcept -> std::size_t + { + constexpr auto field_offset = offsetof(madt_entry_data, length); + + return static_cast(*(m_data.data() + field_offset)); + } + + struct [[gnu::packed]] processor_local_apic_entry_data + { + std::uint8_t apic_id; + std::uint8_t processor_id; + std::uint32_t flags; + }; + + static_assert(sizeof(processor_local_apic_entry_data) == 6); + + auto processor_local_apic_entry::id() const noexcept -> std::uint8_t + { + constexpr auto field_offset = offsetof(processor_local_apic_entry_data, apic_id); + + return static_cast(*(m_data.data() + field_offset)); + } + + auto processor_local_apic_entry::flags() const noexcept -> enum flags + { + using type = decltype(processor_local_apic_entry_data::flags); + static_assert(sizeof(type) == sizeof(enum flags)); + + constexpr auto size = sizeof(type); + constexpr auto offset = offsetof(processor_local_apic_entry_data, flags); + + auto const data = std::span{m_data.data() + offset, size}; + auto value = type{}; + + kstd::libc::memcpy(&value, data.data(), size); + + return static_cast(value); + } + + auto processor_local_apic_entry::processor_id() const noexcept -> std::uint32_t + { + constexpr auto field_offset = offsetof(processor_local_apic_entry_data, processor_id); + + return static_cast(*(m_data.data() + field_offset)); + } + +} // namespace acpi diff --git a/libs/acpi/acpi/data/madt.hpp b/libs/acpi/acpi/data/madt.hpp new file mode 100644 index 0000000..8307826 --- /dev/null +++ b/libs/acpi/acpi/data/madt.hpp @@ -0,0 +1,117 @@ +#ifndef ACPI_ACPI_MADT_HPP +#define ACPI_ACPI_MADT_HPP + +// IWYU pragma: private, include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace acpi +{ + + template<> + struct table_signature + { + constexpr char static const value[] = "APIC"; // NOLINT + }; + + template<> + struct table_type> + { + using type = struct madt; + }; + + struct madt_entry + { + //! The type of an MADT entry. + enum struct type : std::uint8_t + { + processor_local_apic, + io_apic, + io_apic_interrupt_source_override, + io_apic_nmi_source, + local_apic_nmi_interrupts, + local_apic_address_override, + processor_local_x2_apic, + }; + + //! Get the type of this entry. + [[nodiscard]] auto type() const noexcept -> enum type; + + //! Get the length of this entry. + [[nodiscard]] auto length() const noexcept -> std::size_t; + + //! Cast this entry to the given concrete entry type. + //! + //! @warning This function will terminate execution if the desired target type does not match up with this entry's + //! actual type. + template + [[nodiscard]] auto as() const -> EntryType const & + { + if (type() != EntryType::this_type) + { + kstd::os::panic("Invalid cast"); + } + return reinterpret_cast(*this); + } + + private: + std::array m_data{}; + }; + + //! The Multiple APIC Description Table (MADT) + struct madt : vla_table + { + //! Get the physical address of the local interrupt controllers described by this entry. + [[nodiscard]] auto local_interrupt_controller_address() const noexcept -> std::uintptr_t; + + [[nodiscard]] auto flags() const noexcept -> std::uint32_t; + + template + [[nodiscard]] auto only() const noexcept + { + return *this | std::views::filter([](auto const & e) { return e.type() == EntryType::this_type; }) | + std::views::transform([](auto const & e) { return e.template as(); }); + } + + private: + std::array m_data{}; + }; + + struct processor_local_apic_entry : madt_entry + { + constexpr auto static this_type = type::processor_local_apic; + + enum struct flags : std::uint32_t + { + processor_enabled = 1, + online_capable = 2, + }; + + [[nodiscard]] auto id() const noexcept -> std::uint8_t; + [[nodiscard]] auto flags() const noexcept -> flags; + [[nodiscard]] auto processor_id() const noexcept -> std::uint32_t; + + private: + std::array m_data{}; + }; + +} // namespace acpi + +template<> +struct kstd::ext::is_bitfield_enum : std::true_type +{ +}; + +#endif diff --git a/libs/acpi/acpi/data/madt.test.cpp b/libs/acpi/acpi/data/madt.test.cpp new file mode 100644 index 0000000..2b74d4c --- /dev/null +++ b/libs/acpi/acpi/data/madt.test.cpp @@ -0,0 +1,55 @@ +#include + +#include +#include +#include + +#include + +SCENARIO("MADT parsing", "[madt]") +{ + GIVEN("The basic compiled MADT containing a single LAPIC entry and the default x86 LAPIC address") + { + auto data = acpi::test_data::tables::basic_madt(); + + WHEN("parsing the table") + { + auto madt = reinterpret_cast(data.data()); + + THEN("the signature is correct") + { + REQUIRE(madt->signature() == "APIC"); + } + + THEN("validate returns true") + { + REQUIRE(madt->validate()); + } + + THEN("there is a single entry in the table") + { + REQUIRE(std::distance(madt->begin(), madt->end()) == 1); + } + + THEN("the LAPIC address is 0xfee00000") + { + REQUIRE(madt->local_interrupt_controller_address() == 0xfee0'0000); + } + + THEN("the length is sizeof(madt) + sizeof(processor_local_apic)") + { + REQUIRE(madt->length() == sizeof(acpi::madt) + sizeof(acpi::processor_local_apic_entry)); + } + + THEN("the first entry has type processor_local_apic") + { + REQUIRE(madt->cbegin()->type() == acpi::madt_entry::type::processor_local_apic); + } + + THEN("`only` can be used to get a view of all processor_local_apic entries") + { + REQUIRE(std::ranges::distance(madt->only()) == 1); + } + } + } +} diff --git a/libs/acpi/acpi/madt.cpp b/libs/acpi/acpi/madt.cpp deleted file mode 100644 index c6830ad..0000000 --- a/libs/acpi/acpi/madt.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include - -#include - -#include -#include -#include -#include - -namespace acpi -{ - - struct madt_data - { - std::uint32_t local_interrupt_controller_address; - std::uint32_t flags; - }; - - static_assert(sizeof(madt_data) == 8); - - auto madt::local_interrupt_controller_address() const noexcept -> std::uintptr_t - { - using type = decltype(madt_data::local_interrupt_controller_address); - - constexpr auto size = sizeof(type); - constexpr auto offset = offsetof(madt_data, local_interrupt_controller_address); - - auto const data = std::span{m_data.data() + offset, size}; - auto value = type{}; - - kstd::libc::memcpy(&value, data.data(), size); - - return value; - } - - auto madt::flags() const noexcept -> std::uint32_t - { - using type = decltype(madt_data::flags); - - constexpr auto size = sizeof(type); - constexpr auto offset = offsetof(madt_data, flags); - - auto const data = std::span{m_data.data() + offset, size}; - auto value = type{}; - - kstd::libc::memcpy(&value, data.data(), size); - - return value; - } - - struct madt_entry_data - { - std::uint8_t type; - std::uint8_t length; - }; - - static_assert(sizeof(madt_entry_data) == 2); - - auto madt_entry::type() const noexcept -> enum type - { - constexpr auto field_offset = offsetof(madt_entry_data, type); - - return std::bit_cast(*(m_data.data() + field_offset)); - } - - auto madt_entry::length() const noexcept -> std::size_t - { - constexpr auto field_offset = offsetof(madt_entry_data, length); - - return static_cast(*(m_data.data() + field_offset)); - } - - struct [[gnu::packed]] processor_local_apic_entry_data - { - std::uint8_t apic_id; - std::uint8_t processor_id; - std::uint32_t flags; - }; - - static_assert(sizeof(processor_local_apic_entry_data) == 6); - - auto processor_local_apic_entry::id() const noexcept -> std::uint8_t - { - constexpr auto field_offset = offsetof(processor_local_apic_entry_data, apic_id); - - return static_cast(*(m_data.data() + field_offset)); - } - - auto processor_local_apic_entry::flags() const noexcept -> enum flags - { - using type = decltype(processor_local_apic_entry_data::flags); - static_assert(sizeof(type) == sizeof(enum flags)); - - constexpr auto size = sizeof(type); - constexpr auto offset = offsetof(processor_local_apic_entry_data, flags); - - auto const data = std::span{m_data.data() + offset, size}; - auto value = type{}; - - kstd::libc::memcpy(&value, data.data(), size); - - return static_cast(value); - } - - auto processor_local_apic_entry::processor_id() const noexcept -> std::uint32_t - { - constexpr auto field_offset = offsetof(processor_local_apic_entry_data, processor_id); - - return static_cast(*(m_data.data() + field_offset)); - } - -} // namespace acpi diff --git a/libs/acpi/acpi/madt.hpp b/libs/acpi/acpi/madt.hpp deleted file mode 100644 index 8307826..0000000 --- a/libs/acpi/acpi/madt.hpp +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef ACPI_ACPI_MADT_HPP -#define ACPI_ACPI_MADT_HPP - -// IWYU pragma: private, include - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -namespace acpi -{ - - template<> - struct table_signature - { - constexpr char static const value[] = "APIC"; // NOLINT - }; - - template<> - struct table_type> - { - using type = struct madt; - }; - - struct madt_entry - { - //! The type of an MADT entry. - enum struct type : std::uint8_t - { - processor_local_apic, - io_apic, - io_apic_interrupt_source_override, - io_apic_nmi_source, - local_apic_nmi_interrupts, - local_apic_address_override, - processor_local_x2_apic, - }; - - //! Get the type of this entry. - [[nodiscard]] auto type() const noexcept -> enum type; - - //! Get the length of this entry. - [[nodiscard]] auto length() const noexcept -> std::size_t; - - //! Cast this entry to the given concrete entry type. - //! - //! @warning This function will terminate execution if the desired target type does not match up with this entry's - //! actual type. - template - [[nodiscard]] auto as() const -> EntryType const & - { - if (type() != EntryType::this_type) - { - kstd::os::panic("Invalid cast"); - } - return reinterpret_cast(*this); - } - - private: - std::array m_data{}; - }; - - //! The Multiple APIC Description Table (MADT) - struct madt : vla_table - { - //! Get the physical address of the local interrupt controllers described by this entry. - [[nodiscard]] auto local_interrupt_controller_address() const noexcept -> std::uintptr_t; - - [[nodiscard]] auto flags() const noexcept -> std::uint32_t; - - template - [[nodiscard]] auto only() const noexcept - { - return *this | std::views::filter([](auto const & e) { return e.type() == EntryType::this_type; }) | - std::views::transform([](auto const & e) { return e.template as(); }); - } - - private: - std::array m_data{}; - }; - - struct processor_local_apic_entry : madt_entry - { - constexpr auto static this_type = type::processor_local_apic; - - enum struct flags : std::uint32_t - { - processor_enabled = 1, - online_capable = 2, - }; - - [[nodiscard]] auto id() const noexcept -> std::uint8_t; - [[nodiscard]] auto flags() const noexcept -> flags; - [[nodiscard]] auto processor_id() const noexcept -> std::uint32_t; - - private: - std::array m_data{}; - }; - -} // namespace acpi - -template<> -struct kstd::ext::is_bitfield_enum : std::true_type -{ -}; - -#endif diff --git a/libs/acpi/acpi/madt.test.cpp b/libs/acpi/acpi/madt.test.cpp deleted file mode 100644 index 899a377..0000000 --- a/libs/acpi/acpi/madt.test.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include - -#include -#include -#include - -#include - -SCENARIO("MADT parsing", "[madt]") -{ - GIVEN("The basic compiled MADT containing a single LAPIC entry and the default x86 LAPIC address") - { - auto data = acpi::test_data::tables::basic_madt(); - - WHEN("parsing the table") - { - auto madt = reinterpret_cast(data.data()); - - THEN("the signature is correct") - { - REQUIRE(madt->signature() == "APIC"); - } - - THEN("validate returns true") - { - REQUIRE(madt->validate()); - } - - THEN("there is a single entry in the table") - { - REQUIRE(std::distance(madt->begin(), madt->end()) == 1); - } - - THEN("the LAPIC address is 0xfee00000") - { - REQUIRE(madt->local_interrupt_controller_address() == 0xfee0'0000); - } - - THEN("the length is sizeof(madt) + sizeof(processor_local_apic)") - { - REQUIRE(madt->length() == sizeof(acpi::madt) + sizeof(acpi::processor_local_apic_entry)); - } - - THEN("the first entry has type processor_local_apic") - { - REQUIRE(madt->cbegin()->type() == acpi::madt_entry::type::processor_local_apic); - } - - THEN("`only` can be used to get a view of all processor_local_apic entries") - { - REQUIRE(std::ranges::distance(madt->only()) == 1); - } - } - } -} -- cgit v1.2.3