From 4edbe94ce1266c9acc6a695fedf1d2edd4ce11cd Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 24 Jul 2025 15:31:31 +0000 Subject: build: factor out kernel API --- kapi/include/kapi/io.hpp | 17 +++++++++++++++++ kapi/include/kapi/memory.hpp | 9 +++++++++ kapi/include/kapi/system.hpp | 14 ++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 kapi/include/kapi/io.hpp create mode 100644 kapi/include/kapi/memory.hpp create mode 100644 kapi/include/kapi/system.hpp (limited to 'kapi/include') diff --git a/kapi/include/kapi/io.hpp b/kapi/include/kapi/io.hpp new file mode 100644 index 0000000..764738f --- /dev/null +++ b/kapi/include/kapi/io.hpp @@ -0,0 +1,17 @@ +#ifndef TEACHOS_KAPI_IO_HPP +#define TEACHOS_KAPI_IO_HPP + +#include + +namespace teachos::io +{ + auto init() -> void; + + auto print(std::string_view text) -> void; + auto println(std::string_view text) -> void; + + auto print_error(std::string_view text) -> void; + auto println_error(std::string_view text) -> void; +} // namespace teachos::io + +#endif diff --git a/kapi/include/kapi/memory.hpp b/kapi/include/kapi/memory.hpp new file mode 100644 index 0000000..842a2fa --- /dev/null +++ b/kapi/include/kapi/memory.hpp @@ -0,0 +1,9 @@ +#ifndef TEACHOS_KAPI_MEMORY_HPP +#define TEACHOS_KAPI_MEMORY_HPP + +namespace teachos::memory +{ + auto init() -> void; +} + +#endif diff --git a/kapi/include/kapi/system.hpp b/kapi/include/kapi/system.hpp new file mode 100644 index 0000000..0d4f2c9 --- /dev/null +++ b/kapi/include/kapi/system.hpp @@ -0,0 +1,14 @@ +#ifndef TEACHOS_KAPI_SYSTEM_HPP +#define TEACHOS_KAPI_SYSTEM_HPP + +#include +#include + +namespace teachos::system +{ + [[noreturn]] auto halt() -> void; + + [[noreturn]] auto panic(std::string_view message, std::source_location = std::source_location::current()) -> void; +} // namespace teachos::system + +#endif -- cgit v1.2.3 From dd04850c27e8bc273506f4a64bb28b7ddf111dc5 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 24 Jul 2025 20:51:55 +0000 Subject: kapi: rework text device interface --- kapi/include/kapi/cio.hpp | 29 +++++++++++++++++++++++++++++ kapi/include/kapi/io.hpp | 17 ----------------- 2 files changed, 29 insertions(+), 17 deletions(-) create mode 100644 kapi/include/kapi/cio.hpp delete mode 100644 kapi/include/kapi/io.hpp (limited to 'kapi/include') diff --git a/kapi/include/kapi/cio.hpp b/kapi/include/kapi/cio.hpp new file mode 100644 index 0000000..6b93638 --- /dev/null +++ b/kapi/include/kapi/cio.hpp @@ -0,0 +1,29 @@ +#ifndef TEACHOS_KAPI_IO_HPP +#define TEACHOS_KAPI_IO_HPP + +#include +#include + +namespace teachos::cio +{ + struct output_device + { + auto virtual write(std::string_view text [[maybe_unused]]) -> void {} + auto virtual writeln(std::string_view text [[maybe_unused]]) -> void {} + + auto virtual write_error(std::string_view text [[maybe_unused]]) -> void {} + auto virtual writeln_error(std::string_view text [[maybe_unused]]) -> void {} + }; + + auto init() -> void; + + auto set_output_device(output_device & device) -> std::optional; + + auto print(std::string_view text) -> void; + auto println(std::string_view text) -> void; + + auto print_error(std::string_view text) -> void; + auto println_error(std::string_view text) -> void; +} // namespace teachos::cio + +#endif diff --git a/kapi/include/kapi/io.hpp b/kapi/include/kapi/io.hpp deleted file mode 100644 index 764738f..0000000 --- a/kapi/include/kapi/io.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef TEACHOS_KAPI_IO_HPP -#define TEACHOS_KAPI_IO_HPP - -#include - -namespace teachos::io -{ - auto init() -> void; - - auto print(std::string_view text) -> void; - auto println(std::string_view text) -> void; - - auto print_error(std::string_view text) -> void; - auto println_error(std::string_view text) -> void; -} // namespace teachos::io - -#endif -- cgit v1.2.3 From 6434de8ff75a9143847ef529bc209790ac4909b3 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 29 Oct 2025 11:09:42 +0100 Subject: kapi: move frame and address to KAPI --- kapi/include/kapi/memory.hpp | 5 +- kapi/include/kapi/memory/address.hpp | 47 ++++++++++++++++++ kapi/include/kapi/memory/frame.hpp | 92 ++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 kapi/include/kapi/memory/address.hpp create mode 100644 kapi/include/kapi/memory/frame.hpp (limited to 'kapi/include') diff --git a/kapi/include/kapi/memory.hpp b/kapi/include/kapi/memory.hpp index 842a2fa..3ad5ac5 100644 --- a/kapi/include/kapi/memory.hpp +++ b/kapi/include/kapi/memory.hpp @@ -1,9 +1,12 @@ #ifndef TEACHOS_KAPI_MEMORY_HPP #define TEACHOS_KAPI_MEMORY_HPP +#include "kapi/memory/address.hpp" // IWYU pragma: export +#include "kapi/memory/frame.hpp" // IWYU pragma: export + namespace teachos::memory { auto init() -> void; -} +} // namespace teachos::memory #endif diff --git a/kapi/include/kapi/memory/address.hpp b/kapi/include/kapi/memory/address.hpp new file mode 100644 index 0000000..585807a --- /dev/null +++ b/kapi/include/kapi/memory/address.hpp @@ -0,0 +1,47 @@ +#ifndef TEACHOS_KAPI_MEMORY_ADDRESS_HPP +#define TEACHOS_KAPI_MEMORY_ADDRESS_HPP + +#include +#include +#include +#include + +namespace teachos::memory +{ + + enum struct address_type : bool + { + linear, + physical, + }; + + template + struct address + { + constexpr explicit address(std::uintptr_t value) noexcept + : m_value{value} + { + } + + explicit address(std::byte * pointer) noexcept + : m_value{std::bit_cast(pointer)} + { + } + + explicit operator std::byte *() const noexcept { return std::bit_cast(m_value); } + + auto constexpr operator<=>(address const &) const noexcept -> std::strong_ordering = default; + auto constexpr operator==(address const &) const noexcept -> bool = default; + + auto constexpr raw() const noexcept -> std::uintptr_t { return m_value; } + + private: + std::uintptr_t m_value{}; + }; + + using linear_address = address; + using physical_address = address; + +} // namespace teachos::memory + +#endif \ No newline at end of file diff --git a/kapi/include/kapi/memory/frame.hpp b/kapi/include/kapi/memory/frame.hpp new file mode 100644 index 0000000..1251e51 --- /dev/null +++ b/kapi/include/kapi/memory/frame.hpp @@ -0,0 +1,92 @@ +#ifndef TEACHOS_KAPI_MEMORY_FRAME_HPP +#define TEACHOS_KAPI_MEMORY_FRAME_HPP + +#include "kapi/memory/address.hpp" + +#include +#include +#include +#include + +namespace teachos::memory +{ + + extern std::size_t const PLATFORM_FRAME_SIZE; + + struct frame + { + constexpr frame() = default; + + explicit constexpr frame(std::size_t number) + : m_number{number} + { + } + + /** + * @brief Returns the physical frame the given address is contained in. + * + * @param address Physical address we want to get the corresponding physical frame for. + * @return Frame the given address is contained in. + */ + auto constexpr static containing(physical_address address) noexcept -> frame + { + return frame{address.raw() / PLATFORM_FRAME_SIZE}; + } + + /** + * @brief Get the start address of this physical frame. + * + * @return Start address of the physical frame. + */ + auto constexpr start_address() const noexcept -> physical_address + { + return physical_address{m_number * PLATFORM_FRAME_SIZE}; + } + + /** + * @brief Get the nth next frame. + * + * @param offset + * @return A new frame n frames after this one. + */ + auto constexpr operator+(std::size_t n) const noexcept -> frame { return frame{m_number + n}; } + + /** + * @brief Increment this frame to refer to the next one, returning a copy. + * + * @return Copy of the incremented underlying frame number. + */ + auto constexpr operator++(int) noexcept -> frame + { + auto copy = *this; + return ++copy; + } + + /** + * @brief Increment this frame to refer to the next one, returning a this frame. + * + * @return Reference to the incremented underlying frame number. + */ + auto constexpr operator++() noexcept -> frame & + { + ++m_number; + return *this; + } + + /** + * @brief Check if this frame refers to the same frame as @p other. + */ + auto constexpr operator==(frame const & other) const noexcept -> bool = default; + + /** + * @brief Lexicographically compare this frame to @p other. + */ + auto constexpr operator<=>(frame const & other) const noexcept -> std::strong_ordering = default; + + private: + std::size_t m_number{}; + }; + +} // namespace teachos::memory + +#endif \ No newline at end of file -- cgit v1.2.3 From e7b04ef7f5da8e014e8b85fcf65448b317cca8ff Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 29 Oct 2025 11:15:50 +0100 Subject: kapi: move halt to cpu namespace --- kapi/include/kapi/cpu.hpp | 13 +++++++++++++ kapi/include/kapi/system.hpp | 2 -- 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 kapi/include/kapi/cpu.hpp (limited to 'kapi/include') diff --git a/kapi/include/kapi/cpu.hpp b/kapi/include/kapi/cpu.hpp new file mode 100644 index 0000000..673deab --- /dev/null +++ b/kapi/include/kapi/cpu.hpp @@ -0,0 +1,13 @@ +#ifndef TEACHOS_KAPI_CPU_HPP +#define TEACHOS_KAPI_CPU_HPP + +namespace teachos::cpu +{ + /** + * @brief Halt the CPU, effectively terminating kernel execution. + * + */ + [[noreturn]] auto halt() -> void; +} // namespace teachos::cpu + +#endif diff --git a/kapi/include/kapi/system.hpp b/kapi/include/kapi/system.hpp index 0d4f2c9..b0b0e28 100644 --- a/kapi/include/kapi/system.hpp +++ b/kapi/include/kapi/system.hpp @@ -6,8 +6,6 @@ namespace teachos::system { - [[noreturn]] auto halt() -> void; - [[noreturn]] auto panic(std::string_view message, std::source_location = std::source_location::current()) -> void; } // namespace teachos::system -- cgit v1.2.3 From 845a96f5e6bfbbbeba19bf3df07f0e9de53d9a88 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 29 Oct 2025 11:40:49 +0100 Subject: kapi: export frame_allocator interface --- kapi/include/kapi/memory.hpp | 6 ++++-- kapi/include/kapi/memory/frame_allocator.hpp | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 kapi/include/kapi/memory/frame_allocator.hpp (limited to 'kapi/include') diff --git a/kapi/include/kapi/memory.hpp b/kapi/include/kapi/memory.hpp index 3ad5ac5..3daaa86 100644 --- a/kapi/include/kapi/memory.hpp +++ b/kapi/include/kapi/memory.hpp @@ -1,11 +1,13 @@ #ifndef TEACHOS_KAPI_MEMORY_HPP #define TEACHOS_KAPI_MEMORY_HPP -#include "kapi/memory/address.hpp" // IWYU pragma: export -#include "kapi/memory/frame.hpp" // IWYU pragma: export +#include "kapi/memory/address.hpp" // IWYU pragma: export +#include "kapi/memory/frame.hpp" // IWYU pragma: export +#include "kapi/memory/frame_allocator.hpp" // IWYU pragma: export namespace teachos::memory { + auto active_allocator() -> frame_allocator &; auto init() -> void; } // namespace teachos::memory diff --git a/kapi/include/kapi/memory/frame_allocator.hpp b/kapi/include/kapi/memory/frame_allocator.hpp new file mode 100644 index 0000000..f9393ee --- /dev/null +++ b/kapi/include/kapi/memory/frame_allocator.hpp @@ -0,0 +1,19 @@ +#ifndef TEACHOS_KAPI_MEMORY_FRAME_ALLOCATOR_HPP +#define TEACHOS_KAPI_MEMORY_FRAME_ALLOCATOR_HPP + +#include "kapi/memory/frame.hpp" + +#include + +namespace teachos::memory +{ + + struct frame_allocator + { + virtual auto allocate() -> std::optional = 0; + virtual auto release(frame frame) -> void = 0; + }; + +} // namespace teachos::memory + +#endif // TEACHOS_KAPI_MEMORY_FRAME_ALLOCATOR_HPP \ No newline at end of file -- cgit v1.2.3 From 3a0b5678af98832e480115c409495ce835642a09 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 29 Oct 2025 12:26:52 +0100 Subject: kapi/memory: fix frame number postfix increment --- kapi/include/kapi/memory/frame.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'kapi/include') diff --git a/kapi/include/kapi/memory/frame.hpp b/kapi/include/kapi/memory/frame.hpp index 1251e51..8bcf79f 100644 --- a/kapi/include/kapi/memory/frame.hpp +++ b/kapi/include/kapi/memory/frame.hpp @@ -59,7 +59,8 @@ namespace teachos::memory auto constexpr operator++(int) noexcept -> frame { auto copy = *this; - return ++copy; + ++*this; + return copy; } /** -- cgit v1.2.3 From b157e2c472d8bd67ac1656404a6a6ee821260f4b Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 29 Oct 2025 15:01:43 +0100 Subject: chore: reformat source code --- kapi/include/kapi/memory/address.hpp | 18 +++++++++++------- kapi/include/kapi/memory/frame.hpp | 20 +++++++++++--------- 2 files changed, 22 insertions(+), 16 deletions(-) (limited to 'kapi/include') diff --git a/kapi/include/kapi/memory/address.hpp b/kapi/include/kapi/memory/address.hpp index 585807a..63301aa 100644 --- a/kapi/include/kapi/memory/address.hpp +++ b/kapi/include/kapi/memory/address.hpp @@ -20,20 +20,24 @@ namespace teachos::memory { constexpr explicit address(std::uintptr_t value) noexcept : m_value{value} - { - } + {} explicit address(std::byte * pointer) noexcept : m_value{std::bit_cast(pointer)} + {} + + explicit operator std::byte *() const noexcept { + return std::bit_cast(m_value); } - explicit operator std::byte *() const noexcept { return std::bit_cast(m_value); } + constexpr auto operator<=>(address const &) const noexcept -> std::strong_ordering = default; + constexpr auto operator==(address const &) const noexcept -> bool = default; - auto constexpr operator<=>(address const &) const noexcept -> std::strong_ordering = default; - auto constexpr operator==(address const &) const noexcept -> bool = default; - - auto constexpr raw() const noexcept -> std::uintptr_t { return m_value; } + constexpr auto raw() const noexcept -> std::uintptr_t + { + return m_value; + } private: std::uintptr_t m_value{}; diff --git a/kapi/include/kapi/memory/frame.hpp b/kapi/include/kapi/memory/frame.hpp index 8bcf79f..a208f28 100644 --- a/kapi/include/kapi/memory/frame.hpp +++ b/kapi/include/kapi/memory/frame.hpp @@ -19,8 +19,7 @@ namespace teachos::memory explicit constexpr frame(std::size_t number) : m_number{number} - { - } + {} /** * @brief Returns the physical frame the given address is contained in. @@ -28,7 +27,7 @@ namespace teachos::memory * @param address Physical address we want to get the corresponding physical frame for. * @return Frame the given address is contained in. */ - auto constexpr static containing(physical_address address) noexcept -> frame + constexpr auto static containing(physical_address address) noexcept -> frame { return frame{address.raw() / PLATFORM_FRAME_SIZE}; } @@ -38,7 +37,7 @@ namespace teachos::memory * * @return Start address of the physical frame. */ - auto constexpr start_address() const noexcept -> physical_address + constexpr auto start_address() const noexcept -> physical_address { return physical_address{m_number * PLATFORM_FRAME_SIZE}; } @@ -49,14 +48,17 @@ namespace teachos::memory * @param offset * @return A new frame n frames after this one. */ - auto constexpr operator+(std::size_t n) const noexcept -> frame { return frame{m_number + n}; } + constexpr auto operator+(std::size_t n) const noexcept -> frame + { + return frame{m_number + n}; + } /** * @brief Increment this frame to refer to the next one, returning a copy. * * @return Copy of the incremented underlying frame number. */ - auto constexpr operator++(int) noexcept -> frame + constexpr auto operator++(int) noexcept -> frame { auto copy = *this; ++*this; @@ -68,7 +70,7 @@ namespace teachos::memory * * @return Reference to the incremented underlying frame number. */ - auto constexpr operator++() noexcept -> frame & + constexpr auto operator++() noexcept -> frame & { ++m_number; return *this; @@ -77,12 +79,12 @@ namespace teachos::memory /** * @brief Check if this frame refers to the same frame as @p other. */ - auto constexpr operator==(frame const & other) const noexcept -> bool = default; + constexpr auto operator==(frame const & other) const noexcept -> bool = default; /** * @brief Lexicographically compare this frame to @p other. */ - auto constexpr operator<=>(frame const & other) const noexcept -> std::strong_ordering = default; + constexpr auto operator<=>(frame const & other) const noexcept -> std::strong_ordering = default; private: std::size_t m_number{}; -- cgit v1.2.3 From 7b9df8bec5038e0316540d2397df632fb14c9169 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 29 Oct 2025 17:01:22 +0100 Subject: chore: configure clang-tidy --- kapi/include/kapi/cio.hpp | 3 +++ kapi/include/kapi/memory/address.hpp | 2 +- kapi/include/kapi/memory/frame.hpp | 4 +--- kapi/include/kapi/memory/frame_allocator.hpp | 2 ++ 4 files changed, 7 insertions(+), 4 deletions(-) (limited to 'kapi/include') diff --git a/kapi/include/kapi/cio.hpp b/kapi/include/kapi/cio.hpp index 6b93638..a01af08 100644 --- a/kapi/include/kapi/cio.hpp +++ b/kapi/include/kapi/cio.hpp @@ -6,8 +6,11 @@ namespace teachos::cio { + // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) struct output_device { + virtual ~output_device() = default; + auto virtual write(std::string_view text [[maybe_unused]]) -> void {} auto virtual writeln(std::string_view text [[maybe_unused]]) -> void {} diff --git a/kapi/include/kapi/memory/address.hpp b/kapi/include/kapi/memory/address.hpp index 63301aa..359b5ec 100644 --- a/kapi/include/kapi/memory/address.hpp +++ b/kapi/include/kapi/memory/address.hpp @@ -34,7 +34,7 @@ namespace teachos::memory constexpr auto operator<=>(address const &) const noexcept -> std::strong_ordering = default; constexpr auto operator==(address const &) const noexcept -> bool = default; - constexpr auto raw() const noexcept -> std::uintptr_t + [[nodiscard]] constexpr auto raw() const noexcept -> std::uintptr_t { return m_value; } diff --git a/kapi/include/kapi/memory/frame.hpp b/kapi/include/kapi/memory/frame.hpp index a208f28..63b1e70 100644 --- a/kapi/include/kapi/memory/frame.hpp +++ b/kapi/include/kapi/memory/frame.hpp @@ -3,10 +3,8 @@ #include "kapi/memory/address.hpp" -#include #include #include -#include namespace teachos::memory { @@ -37,7 +35,7 @@ namespace teachos::memory * * @return Start address of the physical frame. */ - constexpr auto start_address() const noexcept -> physical_address + [[nodiscard]] constexpr auto start_address() const noexcept -> physical_address { return physical_address{m_number * PLATFORM_FRAME_SIZE}; } diff --git a/kapi/include/kapi/memory/frame_allocator.hpp b/kapi/include/kapi/memory/frame_allocator.hpp index f9393ee..22102a6 100644 --- a/kapi/include/kapi/memory/frame_allocator.hpp +++ b/kapi/include/kapi/memory/frame_allocator.hpp @@ -8,8 +8,10 @@ namespace teachos::memory { + // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) struct frame_allocator { + virtual ~frame_allocator() = default; virtual auto allocate() -> std::optional = 0; virtual auto release(frame frame) -> void = 0; }; -- cgit v1.2.3 From 886c920b8c943753a56ef4893e074c5754a1aa2d Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 21 Nov 2025 14:53:15 +0100 Subject: kapi: enable default construction for addresses --- kapi/include/kapi/memory/address.hpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'kapi/include') diff --git a/kapi/include/kapi/memory/address.hpp b/kapi/include/kapi/memory/address.hpp index 359b5ec..19615e4 100644 --- a/kapi/include/kapi/memory/address.hpp +++ b/kapi/include/kapi/memory/address.hpp @@ -18,6 +18,8 @@ namespace teachos::memory template struct address { + constexpr explicit address() noexcept = default; + constexpr explicit address(std::uintptr_t value) noexcept : m_value{value} {} -- cgit v1.2.3 From 1a3c20cc9ea191a862eb7e8ac55b3a69ac74ad5e Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 24 Nov 2025 16:59:24 +0100 Subject: x86_64/vga: rely less on magic state --- kapi/include/kapi/boot.hpp | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 kapi/include/kapi/boot.hpp (limited to 'kapi/include') diff --git a/kapi/include/kapi/boot.hpp b/kapi/include/kapi/boot.hpp new file mode 100644 index 0000000..013e180 --- /dev/null +++ b/kapi/include/kapi/boot.hpp @@ -0,0 +1,11 @@ +#ifndef TEACHOS_KAPI_BOOT_HPP +#define TEACHOS_KAPI_BOOT_HPP + +namespace teachos::boot +{ + struct information; + + extern "C" information const bootstrap_information; +} // namespace teachos::boot + +#endif -- cgit v1.2.3 From 1db039ca1c67e8daba8b5ec6d5158cb2110e1410 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 28 Nov 2025 16:06:15 +0100 Subject: x86_64: port basic page and page table abstractions --- kapi/include/kapi/memory.hpp | 1 + kapi/include/kapi/memory/page.hpp | 59 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 kapi/include/kapi/memory/page.hpp (limited to 'kapi/include') diff --git a/kapi/include/kapi/memory.hpp b/kapi/include/kapi/memory.hpp index 3daaa86..4279274 100644 --- a/kapi/include/kapi/memory.hpp +++ b/kapi/include/kapi/memory.hpp @@ -4,6 +4,7 @@ #include "kapi/memory/address.hpp" // IWYU pragma: export #include "kapi/memory/frame.hpp" // IWYU pragma: export #include "kapi/memory/frame_allocator.hpp" // IWYU pragma: export +#include "kapi/memory/page.hpp" // IWYU pragma: export namespace teachos::memory { diff --git a/kapi/include/kapi/memory/page.hpp b/kapi/include/kapi/memory/page.hpp new file mode 100644 index 0000000..2b8e52a --- /dev/null +++ b/kapi/include/kapi/memory/page.hpp @@ -0,0 +1,59 @@ +#ifndef TEACHOS_KAPI_MEMORY_PAGE_HPP +#define TEACHOS_KAPI_MEMORY_PAGE_HPP + +#include "kapi/memory/address.hpp" + +#include +#include + +namespace teachos::memory +{ + + extern std::size_t const PLATFORM_PAGE_SIZE; + + struct page + { + constexpr page() = default; + + explicit constexpr page(std::size_t number) + : m_number{number} + {} + + /** + * @brief Returns the virtual page the given address is contained in. + * + * @param address Linear address we want to get the corresponding virtual page for. + * @return Page the given address is contained in. + */ + constexpr auto static containing(linear_address address) noexcept -> page + { + return page{address.raw() / PLATFORM_PAGE_SIZE}; + } + + /** + * @brief Get the start address of this virtual page. + * + * @return Start address of the virtual page. + */ + [[nodiscard]] constexpr auto start_address() const noexcept -> linear_address + { + return linear_address{m_number * PLATFORM_PAGE_SIZE}; + } + + /** + * @brief Check if this page refers to the same page as @p other. + */ + constexpr auto operator==(page const & other) const noexcept -> bool = default; + + /** + * @brief Lexicographically compare this page to @p other. + */ + constexpr auto operator<=>(page const & other) const noexcept -> std::strong_ordering = default; + + private: + std::size_t m_number{}; + }; + +} // namespace teachos::memory + +#endif \ No newline at end of file -- cgit v1.2.3 From 27eddc3fa8d4c6001f223670d6001554fc47b657 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 1 Dec 2025 15:56:58 +0100 Subject: x86_64/memory: implement PML4 injection --- kapi/include/kapi/memory/address.hpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'kapi/include') diff --git a/kapi/include/kapi/memory/address.hpp b/kapi/include/kapi/memory/address.hpp index 19615e4..ad82f20 100644 --- a/kapi/include/kapi/memory/address.hpp +++ b/kapi/include/kapi/memory/address.hpp @@ -33,6 +33,17 @@ namespace teachos::memory return std::bit_cast(m_value); } + constexpr auto operator>>(std::size_t n) const noexcept -> address + { + return address{m_value >> n}; + } + + template + constexpr auto operator&(MaskType mask) const noexcept -> MaskType + { + return static_cast(m_value & mask); + } + constexpr auto operator<=>(address const &) const noexcept -> std::strong_ordering = default; constexpr auto operator==(address const &) const noexcept -> bool = default; -- cgit v1.2.3 From 005d7ea3df29e736750d409b816caa29cf9bab2f Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 1 Dec 2025 16:04:27 +0100 Subject: kapi: mark memory sub-headers private --- kapi/include/kapi/memory/address.hpp | 2 ++ kapi/include/kapi/memory/frame.hpp | 2 ++ kapi/include/kapi/memory/frame_allocator.hpp | 2 ++ kapi/include/kapi/memory/page.hpp | 2 ++ 4 files changed, 8 insertions(+) (limited to 'kapi/include') diff --git a/kapi/include/kapi/memory/address.hpp b/kapi/include/kapi/memory/address.hpp index ad82f20..b861ef5 100644 --- a/kapi/include/kapi/memory/address.hpp +++ b/kapi/include/kapi/memory/address.hpp @@ -1,6 +1,8 @@ #ifndef TEACHOS_KAPI_MEMORY_ADDRESS_HPP #define TEACHOS_KAPI_MEMORY_ADDRESS_HPP +// IWYU pragma: private, include "kapi/memory.hpp" + #include #include #include diff --git a/kapi/include/kapi/memory/frame.hpp b/kapi/include/kapi/memory/frame.hpp index 63b1e70..095a3df 100644 --- a/kapi/include/kapi/memory/frame.hpp +++ b/kapi/include/kapi/memory/frame.hpp @@ -1,6 +1,8 @@ #ifndef TEACHOS_KAPI_MEMORY_FRAME_HPP #define TEACHOS_KAPI_MEMORY_FRAME_HPP +// IWYU pragma: private, include "kapi/memory.hpp" + #include "kapi/memory/address.hpp" #include diff --git a/kapi/include/kapi/memory/frame_allocator.hpp b/kapi/include/kapi/memory/frame_allocator.hpp index 22102a6..6206860 100644 --- a/kapi/include/kapi/memory/frame_allocator.hpp +++ b/kapi/include/kapi/memory/frame_allocator.hpp @@ -1,6 +1,8 @@ #ifndef TEACHOS_KAPI_MEMORY_FRAME_ALLOCATOR_HPP #define TEACHOS_KAPI_MEMORY_FRAME_ALLOCATOR_HPP +// IWYU pragma: private, include "kapi/memory.hpp" + #include "kapi/memory/frame.hpp" #include diff --git a/kapi/include/kapi/memory/page.hpp b/kapi/include/kapi/memory/page.hpp index 2b8e52a..b84094f 100644 --- a/kapi/include/kapi/memory/page.hpp +++ b/kapi/include/kapi/memory/page.hpp @@ -1,6 +1,8 @@ #ifndef TEACHOS_KAPI_MEMORY_PAGE_HPP #define TEACHOS_KAPI_MEMORY_PAGE_HPP +// IWYU pragma: private, include "kapi/memory.hpp" + #include "kapi/memory/address.hpp" #include -- cgit v1.2.3 From be86be1facfce8fe3f376153b9c582f2c5c026aa Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 2 Dec 2025 12:31:53 +0100 Subject: x86_64/memory: extend scoped_mapping --- kapi/include/kapi/memory/frame.hpp | 5 +++++ kapi/include/kapi/memory/page.hpp | 5 +++++ 2 files changed, 10 insertions(+) (limited to 'kapi/include') diff --git a/kapi/include/kapi/memory/frame.hpp b/kapi/include/kapi/memory/frame.hpp index 095a3df..5793b8b 100644 --- a/kapi/include/kapi/memory/frame.hpp +++ b/kapi/include/kapi/memory/frame.hpp @@ -42,6 +42,11 @@ namespace teachos::memory return physical_address{m_number * PLATFORM_FRAME_SIZE}; } + [[nodiscard]] constexpr auto number() const noexcept -> std::size_t + { + return m_number; + } + /** * @brief Get the nth next frame. * diff --git a/kapi/include/kapi/memory/page.hpp b/kapi/include/kapi/memory/page.hpp index b84094f..473a8b8 100644 --- a/kapi/include/kapi/memory/page.hpp +++ b/kapi/include/kapi/memory/page.hpp @@ -42,6 +42,11 @@ namespace teachos::memory return linear_address{m_number * PLATFORM_PAGE_SIZE}; } + [[nodiscard]] constexpr auto number() const noexcept -> std::size_t + { + return m_number; + } + /** * @brief Check if this page refers to the same page as @p other. */ -- cgit v1.2.3 From 331c070547634a2096c5e2165559fb0f11ee6330 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 2 Dec 2025 18:49:36 +0100 Subject: kapi: make PLATFORM_*_SIZE constexpr --- kapi/include/kapi/memory/frame.hpp | 8 ++++---- kapi/include/kapi/memory/page.hpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'kapi/include') diff --git a/kapi/include/kapi/memory/frame.hpp b/kapi/include/kapi/memory/frame.hpp index 5793b8b..10e4172 100644 --- a/kapi/include/kapi/memory/frame.hpp +++ b/kapi/include/kapi/memory/frame.hpp @@ -11,10 +11,10 @@ namespace teachos::memory { - extern std::size_t const PLATFORM_FRAME_SIZE; - struct frame { + constexpr auto static size = PLATFORM_FRAME_SIZE; + constexpr frame() = default; explicit constexpr frame(std::size_t number) @@ -29,7 +29,7 @@ namespace teachos::memory */ constexpr auto static containing(physical_address address) noexcept -> frame { - return frame{address.raw() / PLATFORM_FRAME_SIZE}; + return frame{address.raw() / size}; } /** @@ -39,7 +39,7 @@ namespace teachos::memory */ [[nodiscard]] constexpr auto start_address() const noexcept -> physical_address { - return physical_address{m_number * PLATFORM_FRAME_SIZE}; + return physical_address{m_number * size}; } [[nodiscard]] constexpr auto number() const noexcept -> std::size_t diff --git a/kapi/include/kapi/memory/page.hpp b/kapi/include/kapi/memory/page.hpp index 473a8b8..9bb22e9 100644 --- a/kapi/include/kapi/memory/page.hpp +++ b/kapi/include/kapi/memory/page.hpp @@ -11,10 +11,10 @@ namespace teachos::memory { - extern std::size_t const PLATFORM_PAGE_SIZE; - struct page { + constexpr auto static size = PLATFORM_FRAME_SIZE; + constexpr page() = default; explicit constexpr page(std::size_t number) @@ -29,7 +29,7 @@ namespace teachos::memory */ constexpr auto static containing(linear_address address) noexcept -> page { - return page{address.raw() / PLATFORM_PAGE_SIZE}; + return page{address.raw() / size}; } /** @@ -39,7 +39,7 @@ namespace teachos::memory */ [[nodiscard]] constexpr auto start_address() const noexcept -> linear_address { - return linear_address{m_number * PLATFORM_PAGE_SIZE}; + return linear_address{m_number * size}; } [[nodiscard]] constexpr auto number() const noexcept -> std::size_t -- cgit v1.2.3 From eafbf588760c289b7f54a4771b39af0ccfe8cf59 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 10 Dec 2025 21:55:42 +0100 Subject: kapi: extract page_mapper interface --- kapi/include/kapi/memory.hpp | 2 + kapi/include/kapi/memory/page_mapper.hpp | 82 ++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 kapi/include/kapi/memory/page_mapper.hpp (limited to 'kapi/include') diff --git a/kapi/include/kapi/memory.hpp b/kapi/include/kapi/memory.hpp index 4279274..9ca1267 100644 --- a/kapi/include/kapi/memory.hpp +++ b/kapi/include/kapi/memory.hpp @@ -5,10 +5,12 @@ #include "kapi/memory/frame.hpp" // IWYU pragma: export #include "kapi/memory/frame_allocator.hpp" // IWYU pragma: export #include "kapi/memory/page.hpp" // IWYU pragma: export +#include "kapi/memory/page_mapper.hpp" // IWYU pragma: export namespace teachos::memory { auto active_allocator() -> frame_allocator &; + auto active_mapper() -> page_mapper &; auto init() -> void; } // namespace teachos::memory diff --git a/kapi/include/kapi/memory/page_mapper.hpp b/kapi/include/kapi/memory/page_mapper.hpp new file mode 100644 index 0000000..aa5cf76 --- /dev/null +++ b/kapi/include/kapi/memory/page_mapper.hpp @@ -0,0 +1,82 @@ +#ifndef TEACHOS_KAPI_MEMORY_PAGE_MAPPER_HPP +#define TEACHOS_KAPI_MEMORY_PAGE_MAPPER_HPP + +// IWYU pragma: private, include "kapi/memory.hpp" + +#include "kapi/memory/frame.hpp" +#include "kapi/memory/page.hpp" + +#include + +#include + +namespace teachos::memory +{ + + // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) + struct page_mapper + { + enum struct flags : std::uint64_t + { + empty, + writable = 1 << 0, + executable = 1 << 1, + uncached = 1 << 2, + supervisor = 1 << 3, + }; + + virtual ~page_mapper() = default; + + /** + * Map a page into a given frame, applying the given flags. + * + * @param page The page to map. + * @param frame The frame to map the page into. + * @param flags The flags to map the page with. + * @return A pointer to the first byte of mapped page. + */ + virtual auto map(page page, frame frame, flags flags) -> std::byte * = 0; + + /** + * Unmap the given page. + * + * @warning If the provided page is not mapped, this function will panic. + * @param page The page to unmap. + */ + virtual auto unmap(page page) -> void = 0; + + /** + * Try to unmap the given page. + * + * @param page The page to unmap + * @return true iff. the page was successfully unmapped, false otherwise. + */ + virtual auto try_unmap(page page) -> bool = 0; + + /** + * Map a page into a given frame, applyint the given flags. + * + * @tparam T The type of data contained in the page. + * @param page The page to map. + * @param frame The frame to map the page into. + * @param flags The flags to map the page with. + * @return A pointer to the first T in the page. + */ + template + [[nodiscard]] auto map_as(page page, frame frame, flags flags) -> T * + { + return std::bit_cast(map(page, frame, flags)); + } + }; + +} // namespace teachos::memory + +namespace kstd::ext +{ + template<> + struct is_bitfield_enum : std::true_type + { + }; +} // namespace kstd::ext + +#endif \ No newline at end of file -- cgit v1.2.3 From 998a001fc621ca0e7560ca09a8acd29469ae3373 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 11 Dec 2025 17:46:02 +0100 Subject: docs: improve documentation --- kapi/include/kapi/memory/frame.hpp | 68 ++++++++++++++-------------- kapi/include/kapi/memory/frame_allocator.hpp | 24 +++++++++- 2 files changed, 55 insertions(+), 37 deletions(-) (limited to 'kapi/include') diff --git a/kapi/include/kapi/memory/frame.hpp b/kapi/include/kapi/memory/frame.hpp index 10e4172..c8bcb92 100644 --- a/kapi/include/kapi/memory/frame.hpp +++ b/kapi/include/kapi/memory/frame.hpp @@ -11,58 +11,57 @@ namespace teachos::memory { + //! A handle to a frame of physical memory. struct frame { + //! The platform-dependent size of a single frame of memory. constexpr auto static size = PLATFORM_FRAME_SIZE; - constexpr frame() = default; + //! Construct a handle referencing the first frame of physical memory. + constexpr frame() noexcept = default; - explicit constexpr frame(std::size_t number) + //! Construct a handle referencing the frame of memory with the given frame number. + explicit constexpr frame(std::size_t number) noexcept : m_number{number} {} - /** - * @brief Returns the physical frame the given address is contained in. - * - * @param address Physical address we want to get the corresponding physical frame for. - * @return Frame the given address is contained in. - */ + //! Construct a new frame handle for the frame containing the given address. + //! + //! @param address A physical address contained by the desired frame. + //! @return A handle to a frame containing the given address. constexpr auto static containing(physical_address address) noexcept -> frame { return frame{address.raw() / size}; } - /** - * @brief Get the start address of this physical frame. - * - * @return Start address of the physical frame. - */ + //! Get the start address of the frame referenced by this handle. + //! + //! @return The address of the first byte contained by the frame referenced by this handle. [[nodiscard]] constexpr auto start_address() const noexcept -> physical_address { return physical_address{m_number * size}; } + //! Get the number of the frame referenced by this handle. + //! + //! @return The zero-based number of the frame referenced by this handle. [[nodiscard]] constexpr auto number() const noexcept -> std::size_t { return m_number; } - /** - * @brief Get the nth next frame. - * - * @param offset - * @return A new frame n frames after this one. - */ + //! Get a handle n frames after the one referenced by this handle. + //! + //! @param n The positive offset to this frame. + //! @return A handle referencing the frame n frames after the one referenced by this handle. constexpr auto operator+(std::size_t n) const noexcept -> frame { return frame{m_number + n}; } - /** - * @brief Increment this frame to refer to the next one, returning a copy. - * - * @return Copy of the incremented underlying frame number. - */ + //! Let this handle reference the next frame after the currently reference one. + //! + //! @return A handle referencing the same frame as this handle did before the operation. constexpr auto operator++(int) noexcept -> frame { auto copy = *this; @@ -70,28 +69,27 @@ namespace teachos::memory return copy; } - /** - * @brief Increment this frame to refer to the next one, returning a this frame. - * - * @return Reference to the incremented underlying frame number. - */ + //! Let this handle reference the next frame after the currently reference one. + //! + //! @return A reference to this handle. constexpr auto operator++() noexcept -> frame & { ++m_number; return *this; } - /** - * @brief Check if this frame refers to the same frame as @p other. - */ + //! Check if this frame handle reference the same frame as another one. + //! + //! @param other Another frame handle. constexpr auto operator==(frame const & other) const noexcept -> bool = default; - /** - * @brief Lexicographically compare this frame to @p other. - */ + //! Compare the number of the frame referenced by this handle to the one reference by another one. + //! + //! @param other Another frame handle. constexpr auto operator<=>(frame const & other) const noexcept -> std::strong_ordering = default; private: + //! The number of the currently referenced frame. std::size_t m_number{}; }; diff --git a/kapi/include/kapi/memory/frame_allocator.hpp b/kapi/include/kapi/memory/frame_allocator.hpp index 6206860..fb6bc0d 100644 --- a/kapi/include/kapi/memory/frame_allocator.hpp +++ b/kapi/include/kapi/memory/frame_allocator.hpp @@ -10,12 +10,32 @@ namespace teachos::memory { - // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) + //! The interface of all frame allocators. + //! + //! A frame allocator is responsible for the allocation, and deallocation, of frames of physical memory. Frames + //! obtained from an allocator shall only be deallocated, or released, via the same allocator. When a frame allocated + //! from one allocator is release via a different one (instance or type), the behavior is undefined. struct frame_allocator { + frame_allocator(frame_allocator const &) = delete; + frame_allocator(frame_allocator &&) = delete; + auto operator=(frame_allocator const &) -> frame_allocator & = delete; + auto operator=(frame_allocator &&) -> frame_allocator & = delete; + virtual ~frame_allocator() = default; - virtual auto allocate() -> std::optional = 0; + + //! Allocate a frame of physical memory. + //! + //! @return An engaged std::optional iff. a new frame could be allocated, std::nullopt otherwise. + virtual auto allocate() noexcept -> std::optional = 0; + + //! Release a frame of physical memory. + //! + //! @param frame A frame of physical memory, previously acquired by a call to the #allocate function. virtual auto release(frame frame) -> void = 0; + + protected: + frame_allocator() = default; }; } // namespace teachos::memory -- cgit v1.2.3 From cf8d0d899ee17db734ce8ab7ee618333eb1767f2 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 11 Dec 2025 18:36:23 +0100 Subject: kapi: finish documentation --- kapi/include/kapi/boot.hpp | 6 +++ kapi/include/kapi/cio.hpp | 61 ++++++++++++++++++++++--- kapi/include/kapi/cpu.hpp | 8 ++-- kapi/include/kapi/memory.hpp | 33 +++++++++++++- kapi/include/kapi/memory/address.hpp | 37 ++++++++++++++- kapi/include/kapi/memory/page.hpp | 39 +++++++++------- kapi/include/kapi/memory/page_mapper.hpp | 77 +++++++++++++++++--------------- kapi/include/kapi/system.hpp | 8 ++++ 8 files changed, 204 insertions(+), 65 deletions(-) (limited to 'kapi/include') diff --git a/kapi/include/kapi/boot.hpp b/kapi/include/kapi/boot.hpp index 013e180..9c344cf 100644 --- a/kapi/include/kapi/boot.hpp +++ b/kapi/include/kapi/boot.hpp @@ -3,8 +3,14 @@ namespace teachos::boot { + //! @qualifier platform-defined + //! Information passed from the early pre-main stage to the kernel executable. + //! + //! The specific structure of this type is defined on a platform level. struct information; + //! @qualifier platform-defined + //! An object passed from the early pre-main stage to the kernel executable. extern "C" information const bootstrap_information; } // namespace teachos::boot diff --git a/kapi/include/kapi/cio.hpp b/kapi/include/kapi/cio.hpp index a01af08..a2be97e 100644 --- a/kapi/include/kapi/cio.hpp +++ b/kapi/include/kapi/cio.hpp @@ -6,26 +6,77 @@ namespace teachos::cio { - // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) + + //! The interface of a device able to perform character output on a platform. struct output_device { + output_device(output_device const &) = delete; + output_device(output_device &&) = delete; + auto operator=(output_device const &) -> output_device & = delete; + auto operator=(output_device &&) -> output_device & = delete; + virtual ~output_device() = default; - auto virtual write(std::string_view text [[maybe_unused]]) -> void {} - auto virtual writeln(std::string_view text [[maybe_unused]]) -> void {} + //! Write the given text to the output device. + //! + //! @param text The text to write. + auto virtual write(std::string_view text) -> void = 0; + + //! Write the given text to the output device, appending a newline + //! + //! @param text The text to write. + auto virtual writeln(std::string_view text) -> void = 0; + + //! Write the given error text to the output device. + //! + //! @param text The text to write. + auto virtual write_error(std::string_view text) -> void = 0; - auto virtual write_error(std::string_view text [[maybe_unused]]) -> void {} - auto virtual writeln_error(std::string_view text [[maybe_unused]]) -> void {} + //! Write the given error text to the output device, appending a newline + //! + //! @param text The text to write. + auto virtual writeln_error(std::string_view text) -> void = 0; + + protected: + output_device() = default; }; + //! @qualifier platform-defined + //! Initialize the character I/O subsystem. + //! + //! @note If a platform support character output, it shall ensure that when this function returns, basic character + //! output can be performed on the system. auto init() -> void; + //! @qualifier kernel-defined + //! Set the currently active output device. + //! + //! @param device A new output device. + //! @return The previously active output device. auto set_output_device(output_device & device) -> std::optional; + //! @qualifier kernel-defined + //! Print the given text to the currently active output device. + //! + //! @param text The text to print. auto print(std::string_view text) -> void; + + //! @qualifier kernel-defined + //! Print the given text, including a newline, to the currently active output device. + //! + //! @param text The text to print. auto println(std::string_view text) -> void; + //! @qualifier kernel-defined + //! Print the given error text, to the currently active output device. + //! + //! @param text The error text to print. auto print_error(std::string_view text) -> void; + + //! @qualifier kernel-defined + //! Print the given error text, including a newline, to the currently active output device. + //! + //! @param text The error text to print. auto println_error(std::string_view text) -> void; } // namespace teachos::cio diff --git a/kapi/include/kapi/cpu.hpp b/kapi/include/kapi/cpu.hpp index 673deab..0a26bcf 100644 --- a/kapi/include/kapi/cpu.hpp +++ b/kapi/include/kapi/cpu.hpp @@ -3,10 +3,10 @@ namespace teachos::cpu { - /** - * @brief Halt the CPU, effectively terminating kernel execution. - * - */ + //! @qualifier platform-defined + //! Halt the CPU. + //! + //! This function terminates execution of the kernel. [[noreturn]] auto halt() -> void; } // namespace teachos::cpu diff --git a/kapi/include/kapi/memory.hpp b/kapi/include/kapi/memory.hpp index 9ca1267..2f45611 100644 --- a/kapi/include/kapi/memory.hpp +++ b/kapi/include/kapi/memory.hpp @@ -9,9 +9,38 @@ namespace teachos::memory { - auto active_allocator() -> frame_allocator &; - auto active_mapper() -> page_mapper &; + + //! @qualifier platform-defined + //! Get the currently active frame allocator. + //! + //! @note This function must be implemented by the target platform. + //! + //! @warning If no allocator has been initialized yet, the behavior of this function is platform implementation + //! defined. Implementations are encouraged to terminate execution via a kernel panic. + //! + //! @return A reference to the currently active frame allocator. + auto active_frame_allocator() -> frame_allocator &; + + //! @qualifier platform-defined + //! Get the currently active page mapper. + //! + //! @note This function must be implemented by the target platform. + //! + //! @warning If no mapper has been initialized yet, the behavior of this function is platform implementation + //! defined. Implementations are encouraged to terminate execution via a kernel panic. + //! + //! @return A reference to the currently active page mapper. + auto active_page_mapper() -> page_mapper &; + + //! @qualifier platform-defined + //! Initialize the memory subsystem. + //! + //! @note This function must be implemented by the target platform. + //! + //! This function initializes the memory subsystem and activates the platform-specific frame allocator and page + //! mapper. When this function returns, a valid frame allocator and page mapper are expected to have been registered. auto init() -> void; + } // namespace teachos::memory #endif diff --git a/kapi/include/kapi/memory/address.hpp b/kapi/include/kapi/memory/address.hpp index b861ef5..d5496e4 100644 --- a/kapi/include/kapi/memory/address.hpp +++ b/kapi/include/kapi/memory/address.hpp @@ -11,54 +11,89 @@ namespace teachos::memory { + //! @qualifier kernel-defined + //! A tag for different address types. enum struct address_type : bool { linear, physical, }; + //! @qualifier kernel-defined + //! A physical or virtual address. + //! + //! This convenience wrapper type is used to ensure that no linear address is passed where a physical one is expected + //! and vice versa. + //! + //! @tparam Type The type of address. template struct address { + //! Construct a null-address. constexpr explicit address() noexcept = default; + //! Construct an address representing the given value. + //! + //! @param value The raw value to initialize this address with. constexpr explicit address(std::uintptr_t value) noexcept : m_value{value} {} + //! Construct an address representing the given pointer value. + //! + //! @param pointer The pointer value to initialize this address with. explicit address(std::byte * pointer) noexcept : m_value{std::bit_cast(pointer)} {} + //! Convert this address into a C++ pointer. explicit operator std::byte *() const noexcept { return std::bit_cast(m_value); } + //! Shift this address n bits to the right. + //! + //! @param n The width of the shift. + //! @return A new address representing the result of the shift operation. constexpr auto operator>>(std::size_t n) const noexcept -> address { return address{m_value >> n}; } + //! Apply the given mask to this address. + //! + //! @param mask The mask to apply + //! @return A new address representing the result of the masking operation. template constexpr auto operator&(MaskType mask) const noexcept -> MaskType { return static_cast(m_value & mask); } - constexpr auto operator<=>(address const &) const noexcept -> std::strong_ordering = default; + //! Check if this address is equal to another one. constexpr auto operator==(address const &) const noexcept -> bool = default; + //! Lexicographically compare this address with another one. + constexpr auto operator<=>(address const &) const noexcept -> std::strong_ordering = default; + + //! Extract the raw value from this address. + //! + //! @return The raw value of this address. [[nodiscard]] constexpr auto raw() const noexcept -> std::uintptr_t { return m_value; } private: + //! The raw address value. std::uintptr_t m_value{}; }; + //! A linear/virtual address. using linear_address = address; + + //! A physical address. using physical_address = address; } // namespace teachos::memory diff --git a/kapi/include/kapi/memory/page.hpp b/kapi/include/kapi/memory/page.hpp index 9bb22e9..66e8482 100644 --- a/kapi/include/kapi/memory/page.hpp +++ b/kapi/include/kapi/memory/page.hpp @@ -11,53 +11,58 @@ namespace teachos::memory { + //! @qualifier kernel-defined + //! A handle to a page of virtual memory. struct page { + //! The platform-dependent size of a single page of memory. constexpr auto static size = PLATFORM_FRAME_SIZE; + //! Construct a handle referencing the first page of virtual memory. constexpr page() = default; + //! Construct a handle referencing the page of virtual memory with the given page number. explicit constexpr page(std::size_t number) : m_number{number} {} - /** - * @brief Returns the virtual page the given address is contained in. - * - * @param address Linear address we want to get the corresponding virtual page for. - * @return Page the given address is contained in. - */ + //! Construct a new page handle for the page containing the given address. + //! + //! @param address A linear address contained by the desired page. + //! @return A handle to a page containing the given address. constexpr auto static containing(linear_address address) noexcept -> page { return page{address.raw() / size}; } - /** - * @brief Get the start address of this virtual page. - * - * @return Start address of the virtual page. - */ + //! Get the start address of the page referenced by this handle. + //! + //! @return The address of the first byte contained by the page referenced by this handle. [[nodiscard]] constexpr auto start_address() const noexcept -> linear_address { return linear_address{m_number * size}; } + //! Get the number of the page referenced by this handle. + //! + //! @return The zero-based number of the page referenced by this handle. [[nodiscard]] constexpr auto number() const noexcept -> std::size_t { return m_number; } - /** - * @brief Check if this page refers to the same page as @p other. - */ + //! Check if this page handle reference the same frame as another one. + //! + //! @param other Another page handle. constexpr auto operator==(page const & other) const noexcept -> bool = default; - /** - * @brief Lexicographically compare this page to @p other. - */ + //! Compare the number of the page referenced by this handle to the one reference by another one. + //! + //! @param other Another page handle. constexpr auto operator<=>(page const & other) const noexcept -> std::strong_ordering = default; private: + //! The number of the currently referenced page. std::size_t m_number{}; }; diff --git a/kapi/include/kapi/memory/page_mapper.hpp b/kapi/include/kapi/memory/page_mapper.hpp index aa5cf76..2396249 100644 --- a/kapi/include/kapi/memory/page_mapper.hpp +++ b/kapi/include/kapi/memory/page_mapper.hpp @@ -13,60 +13,65 @@ namespace teachos::memory { - // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) + //! @qualifier platform-implemented + //! The interface of a type allowing the mapping, and unmapping, of pages onto frames. struct page_mapper { + page_mapper(page_mapper const &) = delete; + page_mapper(page_mapper &&) = delete; + auto operator=(page_mapper const &) -> page_mapper & = delete; + auto operator=(page_mapper &&) -> page_mapper & = delete; + + //! Platform independent page mapping flags enum struct flags : std::uint64_t { empty, - writable = 1 << 0, - executable = 1 << 1, - uncached = 1 << 2, - supervisor = 1 << 3, + writable = 1 << 0, //! The page is writable. + executable = 1 << 1, //! The page contains executable instructions. + uncached = 1 << 2, //! The page contents must not be cached. + supervisor_only = 1 << 3, //! The page is only accessible in supervisor mode. }; virtual ~page_mapper() = default; - /** - * Map a page into a given frame, applying the given flags. - * - * @param page The page to map. - * @param frame The frame to map the page into. - * @param flags The flags to map the page with. - * @return A pointer to the first byte of mapped page. - */ + //! Map a page into a given frame, applying the given flags. + //! + //! @param page The page to map. + //! @param frame The frame to map the page into. + //! @param flags The flags to map the page with. + //! @return A pointer to the first byte of mapped page. virtual auto map(page page, frame frame, flags flags) -> std::byte * = 0; - /** - * Unmap the given page. - * - * @warning If the provided page is not mapped, this function will panic. - * @param page The page to unmap. - */ + //! Unmap the given page. + //! + //! @warning If the provided page is not mapped, the behavior is undefined. Implementation are encourage to + //! terminate execution via a kernel panic. + //! + //! @param page The page to unmap. virtual auto unmap(page page) -> void = 0; - /** - * Try to unmap the given page. - * - * @param page The page to unmap - * @return true iff. the page was successfully unmapped, false otherwise. - */ - virtual auto try_unmap(page page) -> bool = 0; - - /** - * Map a page into a given frame, applyint the given flags. - * - * @tparam T The type of data contained in the page. - * @param page The page to map. - * @param frame The frame to map the page into. - * @param flags The flags to map the page with. - * @return A pointer to the first T in the page. - */ + //! Try to unmap the given page. + //! + //! @param page The page to unmap + //! @return true iff. the page was successfully unmapped, false otherwise. + virtual auto try_unmap(page page) noexcept -> bool = 0; + + //! @qualifier kernel-defined + //! Map a page into a given frame, applyint the given flags. + //! + //! @tparam T The type of data contained in the page. + //! @param page The page to map. + //! @param frame The frame to map the page into. + //! @param flags The flags to map the page with. + //! @return A pointer to the first T in the page. template [[nodiscard]] auto map_as(page page, frame frame, flags flags) -> T * { return std::bit_cast(map(page, frame, flags)); } + + protected: + page_mapper() = default; }; } // namespace teachos::memory diff --git a/kapi/include/kapi/system.hpp b/kapi/include/kapi/system.hpp index b0b0e28..e6b9826 100644 --- a/kapi/include/kapi/system.hpp +++ b/kapi/include/kapi/system.hpp @@ -6,7 +6,15 @@ namespace teachos::system { + + //! @qualifier kernel-defined + //! Terminate kernel execution with the given error message. + //! + //! This function terminates the execution of the kernel and attempts to issue the given error message to the user. + //! + //! @param message The message associated with the panic [[noreturn]] auto panic(std::string_view message, std::source_location = std::source_location::current()) -> void; + } // namespace teachos::system #endif -- cgit v1.2.3 From 8fc5f9e3cc28b07b1f120eb1ffedc042fa6662b8 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 12 Dec 2025 13:00:26 +0100 Subject: x86_64/kapi: implement remaining mapping steps --- kapi/include/kapi/boot.hpp | 2 +- kapi/include/kapi/memory/page.hpp | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'kapi/include') diff --git a/kapi/include/kapi/boot.hpp b/kapi/include/kapi/boot.hpp index 9c344cf..dd99198 100644 --- a/kapi/include/kapi/boot.hpp +++ b/kapi/include/kapi/boot.hpp @@ -11,7 +11,7 @@ namespace teachos::boot //! @qualifier platform-defined //! An object passed from the early pre-main stage to the kernel executable. - extern "C" information const bootstrap_information; + extern "C" information bootstrap_information; } // namespace teachos::boot #endif diff --git a/kapi/include/kapi/memory/page.hpp b/kapi/include/kapi/memory/page.hpp index 66e8482..0b7083a 100644 --- a/kapi/include/kapi/memory/page.hpp +++ b/kapi/include/kapi/memory/page.hpp @@ -51,6 +51,15 @@ namespace teachos::memory return m_number; } + //! Get a handle n pages after the one referenced by this handle. + //! + //! @param n The positive offset to this page. + //! @return A handle referencing the page n pages after the one referenced by this handle. + constexpr auto operator+(std::size_t n) const noexcept -> page + { + return page{m_number + n}; + } + //! Check if this page handle reference the same frame as another one. //! //! @param other Another page handle. -- cgit v1.2.3 From 40804526a58ddf2cc0df0750550c8dcfa7b7c57c Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 15 Dec 2025 11:34:30 +0100 Subject: x86_64/boot: use high-mem address of MBI --- kapi/include/kapi/boot.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kapi/include') diff --git a/kapi/include/kapi/boot.hpp b/kapi/include/kapi/boot.hpp index dd99198..9c344cf 100644 --- a/kapi/include/kapi/boot.hpp +++ b/kapi/include/kapi/boot.hpp @@ -11,7 +11,7 @@ namespace teachos::boot //! @qualifier platform-defined //! An object passed from the early pre-main stage to the kernel executable. - extern "C" information bootstrap_information; + extern "C" information const bootstrap_information; } // namespace teachos::boot #endif -- cgit v1.2.3 From e9de1e44a21f4b6d31814ac994b26860d0f6b232 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 15 Dec 2025 16:07:12 +0100 Subject: kapi/memory: extract common base of page and frame --- kapi/include/kapi/memory.hpp | 1 + kapi/include/kapi/memory/chunk.hpp | 104 +++++++++++++++++++++++++++++++++++++ kapi/include/kapi/memory/frame.hpp | 89 ++++++------------------------- kapi/include/kapi/memory/page.hpp | 69 +++++------------------- 4 files changed, 134 insertions(+), 129 deletions(-) create mode 100644 kapi/include/kapi/memory/chunk.hpp (limited to 'kapi/include') diff --git a/kapi/include/kapi/memory.hpp b/kapi/include/kapi/memory.hpp index 2f45611..bed8dbc 100644 --- a/kapi/include/kapi/memory.hpp +++ b/kapi/include/kapi/memory.hpp @@ -2,6 +2,7 @@ #define TEACHOS_KAPI_MEMORY_HPP #include "kapi/memory/address.hpp" // IWYU pragma: export +#include "kapi/memory/chunk.hpp" // IWYU pragma: export #include "kapi/memory/frame.hpp" // IWYU pragma: export #include "kapi/memory/frame_allocator.hpp" // IWYU pragma: export #include "kapi/memory/page.hpp" // IWYU pragma: export diff --git a/kapi/include/kapi/memory/chunk.hpp b/kapi/include/kapi/memory/chunk.hpp new file mode 100644 index 0000000..fde2e36 --- /dev/null +++ b/kapi/include/kapi/memory/chunk.hpp @@ -0,0 +1,104 @@ +#ifndef TEACHOS_KAPI_MEMORY_CHUNK_HPP +#define TEACHOS_KAPI_MEMORY_CHUNK_HPP + +// IWYU pragma: private, include "kapi/memory.hpp" + +#include +#include + +namespace teachos::memory +{ + + //! @qualifier kernel-defined + //! A fixed-size unit of memory, indexed by a number. + //! + //! @tparam AddressType The type of addresses used to index this chunk + //! @tparam Size The size of this chunk. + template + struct chunk + { + //! The type of addresses used to index this chunk + using address_type = AddressType; + + //! The size of this chunk + constexpr auto static size = Size; + + //! Construct a handle referencing the first chunk of the respective address space. + constexpr chunk() noexcept = default; + + //! Construct a handle referencing the chunk of memory with the given number. + explicit constexpr chunk(std::size_t number) noexcept + : m_number{number} + {} + + //! Construct a new chunk handle for the chunk containing the given address. + //! + //! @param address An address contained by the desired chunk. + //! @return A handle to a chunk containing the given address. + constexpr auto static containing(address_type address) noexcept -> chunk + { + return chunk{address.raw() / size}; + } + + //! Get the start address of the chunk referenced by this handle. + //! + //! @return The address of the first byte contained by the chunk referenced by this handle. + [[nodiscard]] constexpr auto start_address() const noexcept -> address_type + { + return address_type{m_number * size}; + } + + //! Get the number of the chunk referenced by this handle. + //! + //! @return The zero-based number of the chunk referenced by this handle. + [[nodiscard]] constexpr auto number() const noexcept -> std::size_t + { + return m_number; + } + + //! Get a handle n chunks after the one referenced by this handle. + //! + //! @param n The positive offset to this chunk. +