aboutsummaryrefslogtreecommitdiff
path: root/kapi
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2025-12-15 17:13:12 +0100
committerFelix Morgner <felix.morgner@ost.ch>2025-12-15 17:13:12 +0100
commit7b9482ae637126ac9337876e60f519b493437711 (patch)
tree6fc71a253c8b0325d303bd34c95b564ba536ed14 /kapi
parent116f9332a206767c45095950f09f7c7447b561cf (diff)
parenta9eeec745e29d89afd48ee43d09432eb6fc35be7 (diff)
downloadteachos-7b9482ae637126ac9337876e60f519b493437711.tar.xz
teachos-7b9482ae637126ac9337876e60f519b493437711.zip
os: rework kernel architecture
Rework the code structure and architecture of the kernel by separating platform-dependent and platform-independent code more cleanly. As of this patchset, full feature parity has not been achieved. Nonetheless, a sufficient subset of functionality has been ported to the new architecture to demonstrate the feasibility of the new structure.
Diffstat (limited to 'kapi')
-rw-r--r--kapi/CMakeLists.txt34
-rw-r--r--kapi/include/kapi/boot.hpp17
-rw-r--r--kapi/include/kapi/cio.hpp51
-rw-r--r--kapi/include/kapi/cio/output_device.hpp47
-rw-r--r--kapi/include/kapi/cpu.hpp13
-rw-r--r--kapi/include/kapi/memory.hpp70
-rw-r--r--kapi/include/kapi/memory/address.hpp101
-rw-r--r--kapi/include/kapi/memory/chunk.hpp104
-rw-r--r--kapi/include/kapi/memory/frame.hpp39
-rw-r--r--kapi/include/kapi/memory/frame_allocator.hpp43
-rw-r--r--kapi/include/kapi/memory/page.hpp39
-rw-r--r--kapi/include/kapi/memory/page_mapper.hpp87
-rw-r--r--kapi/include/kapi/system.hpp20
13 files changed, 665 insertions, 0 deletions
diff --git a/kapi/CMakeLists.txt b/kapi/CMakeLists.txt
new file mode 100644
index 0000000..5e914bb
--- /dev/null
+++ b/kapi/CMakeLists.txt
@@ -0,0 +1,34 @@
+add_library("kapi" INTERFACE)
+add_library("os::kapi" ALIAS "kapi")
+
+target_sources("kapi" PUBLIC
+ FILE_SET HEADERS
+ BASE_DIRS "include"
+ FILES
+ "include/kapi/boot.hpp"
+ "include/kapi/cio.hpp"
+ "include/kapi/memory.hpp"
+ "include/kapi/memory/address.hpp"
+ "include/kapi/memory/frame_allocator.hpp"
+ "include/kapi/memory/frame.hpp"
+ "include/kapi/memory/page_mapper.hpp"
+ "include/kapi/memory/page.hpp"
+ "include/kapi/system.hpp"
+)
+
+target_include_directories("kapi" INTERFACE
+ "include"
+)
+
+target_link_libraries("kapi" INTERFACE
+ "libs::kstd"
+
+ "gcc"
+ "stdc++"
+)
+
+target_compile_definitions("kapi" INTERFACE
+ "PLATFORM_PAGE_SIZE=${TEACHOS_PLATFORM_PAGE_SIZE}uz"
+ "PLATFORM_PAGING_LEVELS=${TEACHOS_PLATFORM_PAGING_LEVELS}uz"
+ "PLATFORM_FRAME_SIZE=${TEACHOS_PLATFORM_FRAME_SIZE}uz"
+)
diff --git a/kapi/include/kapi/boot.hpp b/kapi/include/kapi/boot.hpp
new file mode 100644
index 0000000..9c344cf
--- /dev/null
+++ b/kapi/include/kapi/boot.hpp
@@ -0,0 +1,17 @@
+#ifndef TEACHOS_KAPI_BOOT_HPP
+#define TEACHOS_KAPI_BOOT_HPP
+
+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
+
+#endif
diff --git a/kapi/include/kapi/cio.hpp b/kapi/include/kapi/cio.hpp
new file mode 100644
index 0000000..071e6cb
--- /dev/null
+++ b/kapi/include/kapi/cio.hpp
@@ -0,0 +1,51 @@
+#ifndef TEACHOS_KAPI_CIO_HPP
+#define TEACHOS_KAPI_CIO_HPP
+
+#include "kapi/cio/output_device.hpp" // IWYU pragma: export
+
+#include <optional>
+#include <string_view>
+
+namespace teachos::cio
+{
+
+ //! @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
+
+#endif
diff --git a/kapi/include/kapi/cio/output_device.hpp b/kapi/include/kapi/cio/output_device.hpp
new file mode 100644
index 0000000..0599906
--- /dev/null
+++ b/kapi/include/kapi/cio/output_device.hpp
@@ -0,0 +1,47 @@
+#ifndef TEACHOS_KAPI_CIO_OUTPUT_DEVICE_HPP
+#define TEACHOS_KAPI_CIO_OUTPUT_DEVICE_HPP
+
+// IWYU pragma: private, include "kapi/cio.hpp"
+
+#include <string_view>
+
+namespace teachos::cio
+{
+
+ //! 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;
+
+ //! 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;
+
+ //! 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;
+ };
+
+} // namespace teachos::cio
+
+#endif
diff --git a/kapi/include/kapi/cpu.hpp b/kapi/include/kapi/cpu.hpp
new file mode 100644
index 0000000..0a26bcf
--- /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
+{
+ //! @qualifier platform-defined
+ //! Halt the CPU.
+ //!
+ //! This function terminates execution of the kernel.
+ [[noreturn]] auto halt() -> void;
+} // namespace teachos::cpu
+
+#endif
diff --git a/kapi/include/kapi/memory.hpp b/kapi/include/kapi/memory.hpp
new file mode 100644
index 0000000..b51a8a5
--- /dev/null
+++ b/kapi/include/kapi/memory.hpp
@@ -0,0 +1,70 @@
+#ifndef TEACHOS_KAPI_MEMORY_HPP
+#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
+#include "kapi/memory/page_mapper.hpp" // IWYU pragma: export
+
+#include <cstddef>
+#include <optional>
+
+namespace teachos::memory
+{
+
+ //! @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;
+
+ //! @qualifier kernel-defined
+ //! Set the currently active frame allocator.
+ //!
+ //! @param allocator A new frame allocator.
+ //! @return The previously active frame allocator.
+ auto set_frame_allocator(frame_allocator & allocator) -> std::optional<frame_allocator *>;
+
+ //! @qualifier kernel-defined
+ //! Set the currently active page mapper.
+ //!
+ //! @param mapper A new page mapper.
+ //! @return The previously active page mapper.
+ auto set_page_mapper(page_mapper & mapper) -> std::optional<page_mapper *>;
+
+ //! @qualifier kernel-defined
+ //! Allocate a new frame of physical memory
+ //!
+ //! @warning This function will panic if no frame allocator has been registered.
+ //!
+ //! @return An engaged std::optional iff. a frame could be allocated, std::nullopt otherwise.
+ auto allocate_frame() -> std::optional<frame>;
+
+ //! @qualifier kernel-defined
+ //! Map a page onto a frame.
+ //!
+ //! @warning This function will panic if no page mapper has been registered, or the page has already been mapped.
+ //! This function will not ensure that the frame is not already in use.
+ //!
+ //! @param page The page to map.
+ //! @param frame The frame to map the page into.
+ //! @return A pointer to the first byte of the mapped page.
+ auto map(page page, frame frame) -> std::byte *;
+
+ //! @qualifier kernel-defined
+ //! Unmap a page.
+ //!
+ //! @warning This function will panic if no page mapper has been registered, or the page has already been mapped.
+ //! This function will not ensure that the frame is not already in use.
+ //!
+ //! @param page The page to unmap
+ auto unmap(page page) -> 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..d5496e4
--- /dev/null
+++ b/kapi/include/kapi/memory/address.hpp
@@ -0,0 +1,101 @@
+#ifndef TEACHOS_KAPI_MEMORY_ADDRESS_HPP
+#define TEACHOS_KAPI_MEMORY_ADDRESS_HPP
+
+// IWYU pragma: private, include "kapi/memory.hpp"
+
+#include <bit>
+#include <compare>
+#include <cstddef>
+#include <cstdint>
+
+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);
+ }
+
+ //! 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
+
+#endif \ No newline at end of file
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 <compare>
+#include <cstddef>
+
+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<typename AddressType, std::size_t Size>
+ 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.
+ //! @return A handle referencing the chunk n chunks after the one referenced by this handle.
+ constexpr auto operator+(std::size_t n) const noexcept -> chunk
+ {
+ return chunk{m_number + n};
+ }
+
+ //! Let this handle reference the next chunk after the currently reference one.
+ //!
+ //! @return A handle referencing the same chunk as this handle did before the operation.
+ constexpr auto operator++(int) noexcept -> chunk
+ {
+ auto copy = *this;
+ ++*this;
+ return copy;
+ }
+
+ //! Let this handle reference the next chunk after the currently reference one.
+ //!
+ //! @return A reference to this handle.
+ constexpr auto operator++() noexcept -> chunk &
+ {
+ ++m_number;
+ return *this;
+ }
+
+ //! Check if this chunk handle reference the same chunk as another one.
+ //!
+ //! @param other Another chunk handle.
+ constexpr auto operator==(chunk const & other) const noexcept -> bool = default;
+
+ //! Compare the number of the chunk referenced by this handle to the one reference by another one.
+ //!
+ //! @param other Another chunk handle.
+ constexpr auto operator<=>(chunk const & other) const noexcept -> std::strong_ordering = default;
+
+ private:
+ //! The number of the currently referenced chunk.
+ std::size_t m_number{};
+ };
+
+} // 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..49f3bb0
--- /dev/null
+++ b/kapi/include/kapi/memory/frame.hpp
@@ -0,0 +1,39 @@
+#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 "kapi/memory/chunk.hpp"
+
+namespace teachos::memory
+{
+
+ //! @qualifier kernel-defined
+ //! A handle to a frame of physical memory.
+ //!
+ //! @note Contrary to the address types, this type is modeled using inheritance to support future extensions.
+ struct frame : chunk<physical_address, PLATFORM_FRAME_SIZE>
+ {
+ using chunk::chunk;
+
+ //! @copydoc chunk::containing
+ //!
+ //! @note This factory shadows the base factory to aid in type deduction.
+ constexpr auto static containing(physical_address address) noexcept -> frame
+ {
+ return frame{chunk::containing(address)};
+ }
+
+ //! Convert a base chunk into a page.
+ //!
+ //! This constructor allows for conversion from chunk<physical_address, PLATFORM_FRAME_SIZE> to a frame for
+ //! convenience. It is deliberately not explicit.
+ constexpr frame(chunk other)
+ : chunk{other}
+ {}
+ };
+
+} // namespace teachos::memory
+
+#endif \ No newline at end of file
diff --git a/kapi/include/kapi/memory/frame_allocator.hpp b/kapi/include/kapi/memory/frame_allocator.hpp
new file mode 100644
index 0000000..fb6bc0d
--- /dev/null
+++ b/kapi/include/kapi/memory/frame_allocator.hpp
@@ -0,0 +1,43 @@
+#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 <optional>
+
+namespace teachos::memory
+{
+
+ //! 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;
+
+ //! 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<frame> = 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
+
+#endif // TEACHOS_KAPI_MEMORY_FRAME_ALLOCATOR_HPP \ No newline at end of file
diff --git a/kapi/include/kapi/memory/page.hpp b/kapi/include/kapi/memory/page.hpp
new file mode 100644
index 0000000..57f4f09
--- /dev/null
+++ b/kapi/include/kapi/memory/page.hpp
@@ -0,0 +1,39 @@
+#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 "kapi/memory/chunk.hpp"
+
+namespace teachos::memory
+{
+
+ //! @qualifier kernel-defined
+ //! A handle to a page of virtual memory.
+ //!
+ //! @note Contrary to the address types, this type is modeled using inheritance to support future extensions.
+ struct page : chunk<linear_address, PLATFORM_PAGE_SIZE>
+ {
+ using chunk::chunk;
+
+ //! @copydoc chunk::containing
+ //!
+ //! @note This factory shadows the base factory to aid in type deduction.
+ constexpr auto static containing(linear_address address) noexcept -> page
+ {
+ return page{chunk::containing(address)};
+ }
+
+ //! Convert a base chunk into a page.
+ //!
+ //! This constructor allows for conversion from chunk<linear_address, PLATFORM_PAGE_SIZE> to a page for convenience.
+ //! It is deliberately not explicit.
+ constexpr page(chunk other)
+ : chunk{other}
+ {}
+ };
+
+} // namespace teachos::memory
+
+#endif \ No newline at end of file
diff --git a/kapi/include/kapi/memory/page_mapper.hpp b/kapi/include/kapi/memory/page_mapper.hpp
new file mode 100644
index 0000000..2396249
--- /dev/null
+++ b/kapi/include/kapi/memory/page_mapper.hpp
@@ -0,0 +1,87 @@
+#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 <kstd/ext/bitfield_enum>
+
+#include <type_traits>
+
+namespace teachos::memory
+{
+
+ //! @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, //! 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.
+ virtual auto map(page page, frame frame, flags flags) -> std::byte * = 0;
+
+ //! 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) 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
+
+namespace kstd::ext
+{
+ template<>
+ struct is_bitfield_enum<teachos::memory::page_mapper::flags> : std::true_type
+ {
+ };
+} // namespace kstd::ext
+
+#endif \ No newline at end of file
diff --git a/kapi/include/kapi/system.hpp b/kapi/include/kapi/system.hpp
new file mode 100644
index 0000000..e6b9826
--- /dev/null
+++ b/kapi/include/kapi/system.hpp
@@ -0,0 +1,20 @@
+#ifndef TEACHOS_KAPI_SYSTEM_HPP
+#define TEACHOS_KAPI_SYSTEM_HPP
+
+#include <source_location>
+#include <string_view>
+
+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