aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2025-12-11 18:36:23 +0100
committerFelix Morgner <felix.morgner@ost.ch>2025-12-11 18:36:23 +0100
commitcf8d0d899ee17db734ce8ab7ee618333eb1767f2 (patch)
tree8ff328c106d9f928423dfa860567fbf6dbf84f88
parent998a001fc621ca0e7560ca09a8acd29469ae3373 (diff)
downloadteachos-cf8d0d899ee17db734ce8ab7ee618333eb1767f2.tar.xz
teachos-cf8d0d899ee17db734ce8ab7ee618333eb1767f2.zip
kapi: finish documentation
-rw-r--r--arch/x86_64/include/x86_64/memory/page_table.hpp4
-rw-r--r--arch/x86_64/include/x86_64/memory/recursive_page_mapper.hpp2
-rw-r--r--arch/x86_64/src/kapi/memory.cpp4
-rw-r--r--arch/x86_64/src/memory/paging_root.cpp8
-rw-r--r--arch/x86_64/src/memory/recursive_page_mapper.cpp2
-rw-r--r--arch/x86_64/src/memory/scoped_mapping.cpp4
-rw-r--r--kapi/include/kapi/boot.hpp6
-rw-r--r--kapi/include/kapi/cio.hpp61
-rw-r--r--kapi/include/kapi/cpu.hpp8
-rw-r--r--kapi/include/kapi/memory.hpp33
-rw-r--r--kapi/include/kapi/memory/address.hpp37
-rw-r--r--kapi/include/kapi/memory/page.hpp39
-rw-r--r--kapi/include/kapi/memory/page_mapper.hpp77
-rw-r--r--kapi/include/kapi/system.hpp8
-rw-r--r--kapi/src/cio.cpp21
15 files changed, 234 insertions, 80 deletions
diff --git a/arch/x86_64/include/x86_64/memory/page_table.hpp b/arch/x86_64/include/x86_64/memory/page_table.hpp
index 6c102b7..3bc2a2b 100644
--- a/arch/x86_64/include/x86_64/memory/page_table.hpp
+++ b/arch/x86_64/include/x86_64/memory/page_table.hpp
@@ -246,7 +246,7 @@ namespace teachos::memory::x86_64
if ((flags & table_flags::user_accessible) == table_flags::empty)
{
- result |= mapper_flags::supervisor;
+ result |= mapper_flags::supervisor_only;
}
return result;
@@ -274,7 +274,7 @@ namespace teachos::memory::x86_64
result |= table_flags::disable_cache;
}
- if ((flags & mapper_flags::supervisor) != mapper_flags::empty)
+ if ((flags & mapper_flags::supervisor_only) != mapper_flags::empty)
{
result |= table_flags::user_accessible;
}
diff --git a/arch/x86_64/include/x86_64/memory/recursive_page_mapper.hpp b/arch/x86_64/include/x86_64/memory/recursive_page_mapper.hpp
index a66c8d1..dc52065 100644
--- a/arch/x86_64/include/x86_64/memory/recursive_page_mapper.hpp
+++ b/arch/x86_64/include/x86_64/memory/recursive_page_mapper.hpp
@@ -12,7 +12,7 @@ namespace teachos::memory::x86_64
auto map(page page, frame frame, flags flags) -> std::byte * override;
auto unmap(page page) -> void override;
- auto try_unmap(page page) -> bool override;
+ auto try_unmap(page page) noexcept -> bool override;
private:
frame_allocator * m_allocator;
diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp
index 00b9de3..cd0bd77 100644
--- a/arch/x86_64/src/kapi/memory.cpp
+++ b/arch/x86_64/src/kapi/memory.cpp
@@ -117,7 +117,7 @@ namespace teachos::memory
} // namespace
- auto active_allocator() -> frame_allocator &
+ auto active_frame_allocator() -> frame_allocator &
{
if (!allocator)
{
@@ -127,7 +127,7 @@ namespace teachos::memory
return *allocator;
}
- auto active_mapper() -> page_mapper &
+ auto active_page_mapper() -> page_mapper &
{
if (!mapper)
{
diff --git a/arch/x86_64/src/memory/paging_root.cpp b/arch/x86_64/src/memory/paging_root.cpp
index c458093..078686b 100644
--- a/arch/x86_64/src/memory/paging_root.cpp
+++ b/arch/x86_64/src/memory/paging_root.cpp
@@ -34,7 +34,7 @@ namespace teachos::memory::x86_64
flags = flags | page_table::entry::flags::writable;
if (!(*pml)[index].present())
{
- auto new_table_frame = active_allocator().allocate();
+ auto new_table_frame = active_frame_allocator().allocate();
auto mapping = scoped_mapping{page};
(*pml)[index].frame(new_table_frame.value(), page_table::entry::flags::present | flags);
auto new_table = std::optional{std::construct_at(*pml->next(index))};
@@ -139,21 +139,21 @@ namespace teachos::memory::x86_64
if (pml1->empty())
{
auto pml1_frame = (*pml2)[pml_index<2>(page)].frame().value();
- active_allocator().release(pml1_frame);
+ active_frame_allocator().release(pml1_frame);
(*pml2)[pml_index<2>(page)].clear();
}
if (pml2->empty())
{
auto pml2_frame = (*pml3)[pml_index<3>(page)].frame().value();
- active_allocator().release(pml2_frame);
+ active_frame_allocator().release(pml2_frame);
(*pml3)[pml_index<3>(page)].clear();
}
if (pml3->empty())
{
auto pml3_frame = (*pml4)[pml_index<4>(page)].frame().value();
- active_allocator().release(pml3_frame);
+ active_frame_allocator().release(pml3_frame);
(*pml4)[pml_index<4>(page)].clear();
}
}
diff --git a/arch/x86_64/src/memory/recursive_page_mapper.cpp b/arch/x86_64/src/memory/recursive_page_mapper.cpp
index ea89f38..47148f0 100644
--- a/arch/x86_64/src/memory/recursive_page_mapper.cpp
+++ b/arch/x86_64/src/memory/recursive_page_mapper.cpp
@@ -24,7 +24,7 @@ namespace teachos::memory::x86_64
}
}
- auto recursive_page_mapper::try_unmap(page page) -> bool
+ auto recursive_page_mapper::try_unmap(page page) noexcept -> bool
{
auto & root = paging_root::get();
if (!root.translate(page))
diff --git a/arch/x86_64/src/memory/scoped_mapping.cpp b/arch/x86_64/src/memory/scoped_mapping.cpp
index 6f3461c..e243dc9 100644
--- a/arch/x86_64/src/memory/scoped_mapping.cpp
+++ b/arch/x86_64/src/memory/scoped_mapping.cpp
@@ -44,14 +44,14 @@ namespace teachos::memory::x86_64
auto scoped_mapping::map(frame frame, page_table::entry::flags flags) -> std::byte *
{
- auto result = active_mapper().map(m_page, frame, to_mapper_flags(flags));
+ auto result = active_page_mapper().map(m_page, frame, to_mapper_flags(flags));
m_mapped = true;
return result;
}
auto scoped_mapping::unmap() -> void
{
- active_mapper().unmap(m_page);
+ active_page_mapper().unmap(m_page);
m_mapped = false;
}
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<output_device *>;
+ //! @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<address_type Type>
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<std::uintptr_t>(pointer)}
{}
+ //! Convert this address into a C++ pointer.
explicit operator std::byte *() const noexcept
{
return std::bit_cast<std::byte *>(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<typename MaskType>
constexpr auto operator&(MaskType mask) const noexcept -> MaskType
{
return static_cast<MaskType>(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<address_type::linear>;
+
+ //! A physical address.
using physical_address = address<address_type::physical>;
} // 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<typename T>
[[nodiscard]] auto map_as(page page, frame frame, flags flags) -> T *
{
return std::bit_cast<T *>(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
diff --git a/kapi/src/cio.cpp b/kapi/src/cio.cpp
index 210e58e..66493b6 100644
--- a/kapi/src/cio.cpp
+++ b/kapi/src/cio.cpp
@@ -1,14 +1,29 @@
#include "kapi/cio.hpp"
#include <optional>
+#include <string_view>
#include <utility>
namespace teachos::cio
{
+ namespace
+ {
+ struct null_device final : public output_device
+ {
+ null_device static instance;
+
+ auto write(std::string_view) -> void override {}
+ auto writeln(std::string_view) -> void override {}
+
+ auto write_error(std::string_view) -> void override {}
+ auto writeln_error(std::string_view) -> void override {}
+ };
+
+ constinit null_device null_device::instance;
+ } // namespace
+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
- auto constinit null_device = output_device{};
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
- auto constinit active_device = &null_device;
+ constinit auto active_device = static_cast<output_device *>(&null_device::instance);
auto set_output_device(output_device & device) -> std::optional<output_device *>
{