aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86_64/CMakeLists.txt1
-rw-r--r--arch/x86_64/arch/drivers/cpu/lapic.cpp20
-rw-r--r--arch/x86_64/arch/drivers/init.cpp29
-rw-r--r--arch/x86_64/arch/drivers/init.hpp11
-rw-r--r--arch/x86_64/arch/drivers/pit.cpp18
-rw-r--r--arch/x86_64/kapi/devices.cpp26
-rw-r--r--arch/x86_64/scripts/kernel.ld11
-rw-r--r--kapi/kapi/devices/driver_registry.hpp36
-rw-r--r--kernel/kernel/drivers/init.cpp31
-rw-r--r--kernel/kernel/drivers/pseudo/null.cpp18
-rw-r--r--kernel/kernel/drivers/pseudo/zero.cpp17
-rw-r--r--kernel/kernel/drivers/storage/ram_disk.cpp17
12 files changed, 184 insertions, 51 deletions
diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt
index 19022b5f..fc665c15 100644
--- a/arch/x86_64/CMakeLists.txt
+++ b/arch/x86_64/CMakeLists.txt
@@ -50,7 +50,6 @@ target_sources("x86_64" PRIVATE
"arch/devices/cpu/lapic.cpp"
# Drivers
- "arch/drivers/init.cpp"
"arch/drivers/cpu/lapic.cpp"
"arch/drivers/pit.cpp"
diff --git a/arch/x86_64/arch/drivers/cpu/lapic.cpp b/arch/x86_64/arch/drivers/cpu/lapic.cpp
index 2f74abc4..f8aa8e90 100644
--- a/arch/x86_64/arch/drivers/cpu/lapic.cpp
+++ b/arch/x86_64/arch/drivers/cpu/lapic.cpp
@@ -4,9 +4,11 @@
#include <kapi/capabilities/facet_id.hpp>
#include <kapi/devices.hpp>
+#include <kapi/devices/driver_registry.hpp>
#include <kapi/memory.hpp>
#include <kstd/format.hpp>
+#include <kstd/memory.hpp>
#include <kstd/mutex.hpp>
#include <kstd/print.hpp>
#include <kstd/result.hpp>
@@ -31,6 +33,22 @@ namespace arch::drivers::cpu
constexpr auto offset_of_version = 0u;
constexpr auto offset_of_max_lvt_entry = 16u;
constexpr auto offset_of_eoi_suppression = 24u;
+
+ struct descriptor final : kapi::devices::driver_descriptor
+ {
+ [[nodiscard]] auto make_instance() const -> kstd::shared_ptr<kapi::devices::driver> override
+ {
+ return kstd::make_shared<lapic>();
+ }
+
+ [[nodiscard]] auto name() const noexcept -> std::string_view override
+ {
+ return "intel_lapic";
+ }
+ };
+
+ [[gnu::used]]
+ constexpr auto registration = kapi::devices::platform_driver<descriptor>{};
} // namespace
enum struct lapic::registers : std::ptrdiff_t
@@ -164,4 +182,4 @@ namespace arch::drivers::cpu
return kapi::devices::driver::query_facet(facet);
}
-} // namespace arch::drivers
+} // namespace arch::drivers::cpu
diff --git a/arch/x86_64/arch/drivers/init.cpp b/arch/x86_64/arch/drivers/init.cpp
deleted file mode 100644
index 19f45829..00000000
--- a/arch/x86_64/arch/drivers/init.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <arch/drivers/init.hpp>
-
-#include <arch/drivers/cpu/lapic.hpp>
-#include <arch/drivers/pit.hpp>
-
-#include <kapi/devices.hpp>
-
-#include <kstd/memory.hpp>
-
-#include <cstdint>
-
-namespace arch::drivers
-{
-
- namespace
- {
- //! The interrupt frequency of the Programmable Interrupt Timer.
- constexpr auto pit_frequency_in_hz = std::uint32_t{100u};
- } // namespace
-
- auto init_legacy_drivers() -> void
- {
- auto & driver_registry = kapi::devices::driver_registry::get();
-
- driver_registry.add(kstd::make_shared<pit>(pit_frequency_in_hz));
- driver_registry.add(kstd::make_shared<cpu::lapic>());
- }
-
-} // namespace arch::drivers
diff --git a/arch/x86_64/arch/drivers/init.hpp b/arch/x86_64/arch/drivers/init.hpp
deleted file mode 100644
index 797edb0f..00000000
--- a/arch/x86_64/arch/drivers/init.hpp
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_DRIVERS_INIT_HPP
-#define TEACHOS_ARCH_X86_64_DRIVERS_INIT_HPP
-
-namespace arch::drivers
-{
-
- auto init_legacy_drivers() -> void;
-
-}
-
-#endif
diff --git a/arch/x86_64/arch/drivers/pit.cpp b/arch/x86_64/arch/drivers/pit.cpp
index 49b3f228..e6e98796 100644
--- a/arch/x86_64/arch/drivers/pit.cpp
+++ b/arch/x86_64/arch/drivers/pit.cpp
@@ -29,6 +29,24 @@ namespace arch::drivers
constexpr auto command_offset = 3u;
constexpr auto pit_names = std::array{"pit"sv};
+ constexpr auto pit_frequency_in_hz = std::uint32_t{100u};
+
+ struct descriptor final : kapi::devices::driver_descriptor
+ {
+ [[nodiscard]] auto make_instance() const -> kstd::shared_ptr<kapi::devices::driver> override
+ {
+ return kstd::make_shared<pit>(pit_frequency_in_hz);
+ }
+
+ [[nodiscard]] auto name() const noexcept -> std::string_view override
+ {
+ return "i8253_pit"sv;
+ }
+ };
+
+ [[gnu::used]]
+ constexpr auto registration = kapi::devices::platform_driver<descriptor>{};
+
} // namespace
pit::pit(std::uint32_t frequency_in_hz)
diff --git a/arch/x86_64/kapi/devices.cpp b/arch/x86_64/kapi/devices.cpp
index d9a0b2b9..888b6e20 100644
--- a/arch/x86_64/kapi/devices.cpp
+++ b/arch/x86_64/kapi/devices.cpp
@@ -2,11 +2,15 @@
#include <arch/bus/cpu.hpp>
#include <arch/devices/init.hpp>
-#include <arch/drivers/init.hpp>
+#include <kapi/devices/driver_registry.hpp>
#include <kapi/system.hpp>
#include <kstd/memory.hpp>
+#include <kstd/print.hpp>
+
+#include <ranges>
+#include <span>
namespace kapi::devices
{
@@ -16,9 +20,27 @@ namespace kapi::devices
auto static constinit cpu_bus = kstd::shared_ptr<arch::bus::cpu>{};
}
+ extern "C"
+ {
+ // We need to suppress clang-tidy linting warnings here, since these symbols are generated by the linker and we
+ // cannot choose their names, unless we wanted to extend the linker script needlessly.
+ // NOLINTBEGIN(readability-identifier-naming)
+ extern kstd::observer_ptr<kapi::devices::driver_descriptor> const __start_platform_drivers;
+ extern kstd::observer_ptr<kapi::devices::driver_descriptor> const __stop_platform_drivers;
+ // NOLINTEND(readability-identifier-naming)
+ }
+
auto init_platform_drivers() -> void
{
- arch::drivers::init_legacy_drivers();
+ auto descriptors = std::span{&__start_platform_drivers, &__stop_platform_drivers} | //
+ std::views::filter([](auto p) { return p != nullptr; });
+
+ for (auto driver : descriptors)
+ {
+ auto instance = driver->make_instance();
+ kstd::println("[x86_64:DRV] registering driver '{}' ({})", instance->name(), driver->name());
+ kapi::devices::driver_registry::get().add(driver->make_instance());
+ }
}
auto init_platform_devices() -> void
diff --git a/arch/x86_64/scripts/kernel.ld b/arch/x86_64/scripts/kernel.ld
index dbb0f8f0..f621c3f1 100644
--- a/arch/x86_64/scripts/kernel.ld
+++ b/arch/x86_64/scripts/kernel.ld
@@ -75,9 +75,20 @@ SECTIONS
. = ALIGN(8);
+ /* Filesystem driver factories */
PROVIDE(__start_fs_types = .);
KEEP(*(fs_types));
PROVIDE(__stop_fs_types = .);
+
+ /* Kernel driver factories */
+ PROVIDE(__start_kernel_drivers = .);
+ KEEP(*(kernel_drivers));
+ PROVIDE(__stop_kernel_drivers = .);
+
+ /* Platform driver factories */
+ PROVIDE(__start_platform_drivers = .);
+ KEEP(*(platform_drivers));
+ PROVIDE(__stop_platform_drivers = .);
} :kernel_rodata
.kernel_data ALIGN(4K) : AT (ADDR (.kernel_data) - TEACHOS_VMA)
diff --git a/kapi/kapi/devices/driver_registry.hpp b/kapi/kapi/devices/driver_registry.hpp
index 8af76b01..196b14c1 100644
--- a/kapi/kapi/devices/driver_registry.hpp
+++ b/kapi/kapi/devices/driver_registry.hpp
@@ -8,9 +8,45 @@
#include <kstd/memory.hpp>
#include <kstd/vector.hpp>
+#include <string_view>
+
namespace kapi::devices
{
+ //! @addtogroup kapi-devices
+ //! @{
+
+ struct driver_descriptor
+ {
+ virtual ~driver_descriptor() = default;
+
+ //! Get the name of the driver
+ [[nodiscard]] virtual auto name() const noexcept -> std::string_view = 0;
+
+ //! Create a new instance of the driver represented by this descriptor.
+ [[nodiscard]] virtual auto make_instance() const -> kstd::shared_ptr<driver> = 0;
+ };
+
+ template<typename Type>
+ struct kernel_driver
+ {
+ constexpr auto static instance = Type{};
+ [[using gnu: section("kernel_drivers"), used, visibility("hidden")]] constexpr auto static pointer{
+ kstd::make_observer<kapi::devices::driver_descriptor const>(&instance),
+ };
+ };
+
+ template<typename Type>
+ struct platform_driver
+ {
+ constexpr auto static instance = Type{};
+ [[using gnu: section("platform_drivers"), used, visibility("hidden")]] constexpr auto static pointer{
+ kstd::make_observer<kapi::devices::driver_descriptor const>(&instance),
+ };
+ };
+
+ //! @}
+
//! @addtogroup kapi-devices-kernel-defined
//! @{
diff --git a/kernel/kernel/drivers/init.cpp b/kernel/kernel/drivers/init.cpp
index cd196fa8..97d8f0bc 100644
--- a/kernel/kernel/drivers/init.cpp
+++ b/kernel/kernel/drivers/init.cpp
@@ -1,25 +1,42 @@
#include <kernel/drivers/init.hpp>
-#include <kernel/drivers/pseudo/null.hpp>
-#include <kernel/drivers/pseudo/zero.hpp>
-#include <kernel/drivers/storage/ram_disk.hpp>
-
+#include <kapi/devices.hpp>
#include <kapi/devices/driver_registry.hpp>
#include <kstd/memory.hpp>
+#include <kstd/print.hpp>
+
+#include <ranges>
+#include <span>
namespace kernel::drivers
{
+ extern "C"
+ {
+ // We need to suppress clang-tidy linting warnings here, since these symbols are generated by the linker and we
+ // cannot choose their names, unless we wanted to extend the linker script needlessly.
+ // NOLINTBEGIN(readability-identifier-naming)
+ extern kstd::observer_ptr<kapi::devices::driver_descriptor> const __start_kernel_drivers;
+ extern kstd::observer_ptr<kapi::devices::driver_descriptor> const __stop_kernel_drivers;
+ // NOLINTEND(readability-identifier-naming)
+ }
+
auto init() -> void
{
kapi::devices::driver_registry::init();
auto & registry = kapi::devices::driver_registry::get();
- registry.add(kstd::make_shared<kernel::drivers::pseudo::null>());
- registry.add(kstd::make_shared<kernel::drivers::pseudo::zero>());
- registry.add(kstd::make_shared<kernel::drivers::storage::ram_disk>());
+ auto descriptors = std::span{&__start_kernel_drivers, &__stop_kernel_drivers} | //
+ std::views::filter([](auto p) { return p != nullptr; });
+
+ for (auto driver : descriptors)
+ {
+ auto instance = driver->make_instance();
+ kstd::println("[OS:DRV] registering driver '{}' ({})", instance->name(), driver->name());
+ registry.add(driver->make_instance());
+ }
}
} // namespace kernel::drivers \ No newline at end of file
diff --git a/kernel/kernel/drivers/pseudo/null.cpp b/kernel/kernel/drivers/pseudo/null.cpp
index d0df9000..4995cc25 100644
--- a/kernel/kernel/drivers/pseudo/null.cpp
+++ b/kernel/kernel/drivers/pseudo/null.cpp
@@ -4,6 +4,7 @@
#include <kernel/filesystem/reserved_numbers.hpp>
#include <kapi/devices.hpp>
+#include <kapi/devices/driver_registry.hpp>
#include <kapi/filesystem.hpp>
#include <kstd/memory.hpp>
@@ -26,6 +27,23 @@ namespace kernel::drivers::pseudo
namespace
{
+ struct descriptor final : kapi::devices::driver_descriptor
+ {
+ public:
+ [[nodiscard("")]] auto name() const noexcept -> std::string_view override
+ {
+ return "dev_null";
+ }
+
+ [[nodiscard("")]] auto make_instance() const -> kstd::shared_ptr<kapi::devices::driver> override
+ {
+ return kstd::make_shared<null>();
+ }
+ };
+
+ [[gnu::used]]
+ constexpr auto registration = kapi::devices::kernel_driver<descriptor>{};
+
struct null_node final : kapi::filesystem::character_special_file
{
public:
diff --git a/kernel/kernel/drivers/pseudo/zero.cpp b/kernel/kernel/drivers/pseudo/zero.cpp
index 550a97ff..724ff25c 100644
--- a/kernel/kernel/drivers/pseudo/zero.cpp
+++ b/kernel/kernel/drivers/pseudo/zero.cpp
@@ -27,6 +27,23 @@ namespace kernel::drivers::pseudo
namespace
{
+ struct descriptor final : kapi::devices::driver_descriptor
+ {
+ public:
+ [[nodiscard("")]] auto name() const noexcept -> std::string_view override
+ {
+ return "dev_zero";
+ }
+
+ [[nodiscard("")]] auto make_instance() const -> kstd::shared_ptr<kapi::devices::driver> override
+ {
+ return kstd::make_shared<zero>();
+ }
+ };
+
+ [[gnu::used]]
+ constexpr auto registration = kapi::devices::kernel_driver<descriptor>{};
+
struct zero_node final : kapi::filesystem::character_special_file
{
public:
diff --git a/kernel/kernel/drivers/storage/ram_disk.cpp b/kernel/kernel/drivers/storage/ram_disk.cpp
index 987f4bbc..f7e73cd1 100644
--- a/kernel/kernel/drivers/storage/ram_disk.cpp
+++ b/kernel/kernel/drivers/storage/ram_disk.cpp
@@ -31,6 +31,23 @@ namespace kernel::drivers::storage
{
constexpr auto default_block_size = 512_B;
+ struct descriptor final : kapi::devices::driver_descriptor
+ {
+ public:
+ [[nodiscard("")]] auto name() const noexcept -> std::string_view override
+ {
+ return "ram_disk";
+ }
+
+ [[nodiscard("")]] auto make_instance() const -> kstd::shared_ptr<kapi::devices::driver> override
+ {
+ return kstd::make_shared<ram_disk>();
+ }
+ };
+
+ [[gnu::used]]
+ constexpr auto registration = kapi::devices::kernel_driver<descriptor>{};
+
struct block_node final : kapi::filesystem::block_special_file
{
explicit block_node(kapi::boot_modules::module const & module)