aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-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
12 files changed, 540 insertions, 5 deletions
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>
+
+#include <string_view>
+
+namespace kernel::acpi
+{
+
+ struct manager
+ {
+ explicit manager(kapi::acpi::root_system_description_pointer const & sdp);
+
+ auto load_tables() -> bool;
+
+ auto get_table(std::string_view signature) -> kstd::observer_ptr<kapi::acpi::system_description_table_header const>;
+
+ private:
+ kapi::acpi::root_system_description_pointer const * m_sdp{};
+ kapi::acpi::system_description_table_header const * m_rsdt{};
+ kstd::flat_map<std::string_view, kapi::acpi::system_description_table_header const *> m_tables{};
+ bool m_extended{};
+ };
+
+} // namespace kernel::acpi
+
+#endif
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 <cstddef>
+#include <cstdint>
+
+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/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
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
diff --git a/kernel/src/acpi/manager.cpp b/kernel/src/acpi/manager.cpp
new file mode 100644
index 0000000..300b85e
--- /dev/null
+++ b/kernel/src/acpi/manager.cpp
@@ -0,0 +1,103 @@
+#include "kernel/acpi/manager.hpp"
+
+#include "kapi/acpi.hpp"
+#include "kapi/memory.hpp"
+#include "kapi/system.hpp"
+
+#include <kstd/memory>
+#include <kstd/print>
+
+#include <cstddef>
+#include <cstdint>
+#include <string_view>
+
+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<kapi::acpi::extended_system_description_pointer const *>(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<kapi::acpi::system_description_table_header const *>(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<kapi::acpi::system_description_table_header const *>(linear_root_table_address);
+ }
+ }
+
+ auto manager::load_tables() -> bool
+ {
+ if (!kapi::acpi::validate_checksum({reinterpret_cast<std::byte const *>(m_rsdt), m_rsdt->length().value}))
+ {
+ 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(kapi::acpi::system_description_table_header)) / entry_size;
+ auto entries_base =
+ reinterpret_cast<std::byte const *>(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<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<kapi::acpi::system_description_table_header const *>(linear_table_address);
+
+ if (!kapi::acpi::validate_checksum({reinterpret_cast<std::byte const *>(table), table->length().value}))
+ {
+ kstd::println(kstd::print_sink::stderr, "[OS:ACPI] Invalid table checksum!");
+ }
+ else
+ {
+ kstd::println("[OS:ACPI] Found '{}' ACPI table", table->signature());
+ m_tables.emplace(table->signature(), table);
+ }
+ }
+
+ return !m_tables.empty();
+ }
+
+ auto manager::get_table(std::string_view signature)
+ -> kstd::observer_ptr<kapi::acpi::system_description_table_header const>
+ {
+ 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..eb10d74
--- /dev/null
+++ b/kernel/src/devices/cpu.cpp
@@ -0,0 +1,45 @@
+#include "kernel/devices/cpu.hpp"
+
+#include "kapi/devices.hpp"
+#include "kapi/platform.hpp"
+
+#include <kstd/print>
+
+#include <cstddef>
+#include <cstdint>
+
+namespace kernel::devices
+{
+
+ 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
+ {
+ if (!kapi::platform::discover_cpu_topology(*this))
+ {
+ kstd::println("[OS:DEV] Failed to discover CPU topology");
+ return false;
+ }
+
+ 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.");