diff options
Diffstat (limited to 'arch/x86_64/include')
5 files changed, 224 insertions, 92 deletions
diff --git a/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp index 6cb5f56..a86c9b7 100644 --- a/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp @@ -1,12 +1,12 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP +#ifndef TEACHOS_X86_64_MEMORY_AREA_ALLOCATOR_HPP +#define TEACHOS_X86_64_MEMORY_AREA_ALLOCATOR_HPP -#include "arch/memory/allocator/physical_frame.hpp" -#include "arch/memory/multiboot/reader.hpp" +// #include "arch/memory/allocator/physical_frame.hpp" +// #include "arch/memory/multiboot/reader.hpp" #include <optional> -namespace teachos::arch::memory::allocator +namespace x86_64::memory { /** * @brief Allocates memory linearly using memory areas read from the multiboot2 information pointer and leaks any @@ -62,6 +62,6 @@ namespace teachos::arch::memory::allocator physical_frame const multiboot_end; ///< The end address of the multiboot code in memory. }; -} // namespace teachos::arch::memory::allocator +} // namespace x86_64::memory #endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP diff --git a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp deleted file mode 100644 index cb6c5b3..0000000 --- a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP - -#include "arch/stl/container.hpp" -#include "arch/stl/forward_value_iterator.hpp" - -#include <compare> -#include <cstdint> -#include <iterator> - -namespace teachos::arch::memory::allocator -{ - using physical_address = std::size_t; - - std::size_t constexpr PAGE_FRAME_SIZE = 4096U; ///< Default page size of x86_84 is always 4KiB. - - /** - * @brief Specific physical frame containing helper functions to determine if a specific address is in that - * physical frame or not. - */ - struct physical_frame - { - /** - * @brief Defaulted constructor. - */ - constexpr physical_frame() = default; - - /** - * @brief Constructor. - * - * @param frame_number Index number that should be assigned to this physical frame. - */ - explicit constexpr physical_frame(std::size_t frame_number) - : frame_number(frame_number) - { - // Nothing to do - } - - /** - * @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 static containing_address(physical_address address) -> physical_frame; - - /** - * @brief Get the start address of this physical frame. - * - * @return Start address of the physical frame. - */ - auto start_address() const -> physical_address; - - /** - * @brief Post increment operator. Returns a copy of the value. - * - * @return Copy of the incremented underlying frame number. - */ - auto operator++(int) -> physical_frame; - - /** - * @brief Pre increment operator. Returns a reference to the changed value. - * - * @return Reference to the incremented underlying frame number. - */ - auto operator++() -> physical_frame &; - - /** - * @brief Defaulted equals operator. - */ - auto operator==(physical_frame const & other) const -> bool = default; - - /** - * @brief Defaulted three-way comparsion operator. - */ - auto operator<=>(physical_frame const & other) const -> std::partial_ordering = default; - - std::size_t frame_number = - {}; ///< Index number of the current physical frame, used to distinguish it from other frames. - }; - - using frame_container = stl::container<stl::forward_value_iterator<physical_frame>>; - -} // namespace teachos::arch::memory::allocator - -#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP diff --git a/arch/x86_64/include/x86_64/memory/address.hpp b/arch/x86_64/include/x86_64/memory/address.hpp new file mode 100644 index 0000000..20e9655 --- /dev/null +++ b/arch/x86_64/include/x86_64/memory/address.hpp @@ -0,0 +1,47 @@ +#ifndef TEACHOS_X86_64_MEMORY_ADDRESS_HPP +#define TEACHOS_X86_64_MEMORY_ADDRESS_HPP + +#include <bit> +#include <compare> +#include <cstddef> +#include <cstdint> + +namespace teachos::x86_64::memory +{ + + enum struct address_type : bool + { + linear, + physical, + }; + + template<address_type Type> + struct address + { + constexpr explicit address(std::uintptr_t value) noexcept + : m_value{value} + { + } + + explicit address(std::byte * pointer) noexcept + : m_value{std::bit_cast<std::uintptr_t>(pointer)} + { + } + + explicit operator std::byte *() const noexcept { return std::bit_cast<std::byte *>(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<address_type::linear>; + using physical_address = address<address_type::physical>; + +} // namespace teachos::x86_64::memory + +#endif
\ No newline at end of file diff --git a/arch/x86_64/include/x86_64/memory/frame.hpp b/arch/x86_64/include/x86_64/memory/frame.hpp new file mode 100644 index 0000000..21565fd --- /dev/null +++ b/arch/x86_64/include/x86_64/memory/frame.hpp @@ -0,0 +1,95 @@ +#ifndef TEACHOS_X86_64_MEMORY_FRAME_HPP +#define TEACHOS_X86_64_MEMORY_FRAME_HPP + +#include "x86_64/memory/address.hpp" + +#include <compare> +#include <cstddef> + +namespace teachos::x86_64::memory +{ + /** + * @brief Specific physical frame containing helper functions to determine if a specific address is in that + * physical frame or not. + */ + struct frame + { + auto static inline constexpr DEFAULT_SIZE = std::size_t{4096}; ///< Default page size of x86_84 is always 4KiB. + + /** + * @brief Defaulted constructor. + */ + constexpr frame() = default; + + /** + * @brief Constructor. + * + * @param frame_number Index number that should be assigned to this physical frame. + */ + 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() / DEFAULT_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 * DEFAULT_SIZE}; + } + + auto constexpr operator+(std::size_t offset) const noexcept -> frame { return frame{m_number + offset}; } + + /** + * @brief Post increment operator. Returns a copy of the value. + * + * @return Copy of the incremented underlying frame number. + */ + auto constexpr operator++(int) noexcept -> frame + { + auto copy = *this; + return ++copy; + } + + /** + * @brief Pre increment operator. Returns a reference to the changed value. + * + * @return Reference to the incremented underlying frame number. + */ + auto constexpr operator++() noexcept -> frame & + { + ++m_number; + return *this; + } + + /** + * @brief Defaulted equals operator. + */ + auto constexpr operator==(frame const & other) const noexcept -> bool = default; + + /** + * @brief Defaulted three-way comparison operator. + */ + auto constexpr operator<=>(frame const & other) const noexcept -> std::strong_ordering = default; + + private: + std::size_t m_number{}; ///< Index number of the current physical frame, used to distinguish it from other frames. + }; + +} // namespace teachos::x86_64::memory + +#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_frame_HPP diff --git a/arch/x86_64/include/x86_64/memory/region_allocator.hpp b/arch/x86_64/include/x86_64/memory/region_allocator.hpp new file mode 100644 index 0000000..23bea10 --- /dev/null +++ b/arch/x86_64/include/x86_64/memory/region_allocator.hpp @@ -0,0 +1,76 @@ +#ifndef TEACHOS_X86_64_MEMORY_REGION_ALLOCATOR_HPP +#define TEACHOS_X86_64_MEMORY_REGION_ALLOCATOR_HPP + +#include "x86_64/memory/address.hpp" +#include "x86_64/memory/frame.hpp" + +#include <multiboot2/information.hpp> + +#include <optional> +#include <utility> + +namespace teachos::x86_64::memory +{ + /** + * @brief Allocates memory linearly using memory areas read from the multiboot2 information pointer and leaks any + * deallocated frames. + */ + struct region_allocator + { + struct memory_information + { + std::pair<physical_address, physical_address> image_range; + std::pair<physical_address, physical_address> mbi_range; + multiboot2::memory_map memory_map; + }; + + /** + * @brief Constructor. + * + * @param mem_info Structure containing all relevant information to map and allocate memory. + */ + explicit region_allocator(memory_information const & mem_info); + + /** + * @brief Allocate memory by finding and returning a free physical frame. + * + * @note The physical_frame allocation executes multiple checks before returning + * the physical_frame that is available to allocate. It must at least + * do the following: + * - check if the next_free_frame is within the current_area + * - check if the next_free_frame is actually free + * - update the next_free_frame after finding a free physical_frame + * + * @return next free physical frame or nullopt if none was found. + */ + auto allocate_frame() -> std::optional<frame>; + + /** + * @brief Deallocates a previously allocated physical frame. + * + * @note Simply does nothing, because the simply area frame + * allocator implementation does not keep track of free or used frames and can therefore not deallocate, because it + * does not know which frames have been allocated in the first place. + * + * @param physical_frame Previously allocated physical_frame that should be deallocated. + */ + auto deallocate_frame(frame const & physical_frame) -> void; + + private: + /** + * @brief Find the next memory area and write it into current_area. + */ + auto choose_next_area() -> void; + + frame m_next_frame; ///< The physical_frame after the last allocated one. + std::optional<multiboot2::memory_map::region> m_current_region; ///< The memory region currently allocated from + multiboot2::memory_map m_memory_map; ///< The boot loader supplied memory map. + frame const m_kernel_start; ///< The start address of the kernel code in memory. + frame const m_kernel_end; ///< The end address of the kernel code in memory. + frame const m_multiboot_start; ///< The start address of the multiboot code in memory. + frame const m_multiboot_end; ///< The end address of the multiboot code in memory. + }; + +} // namespace teachos::x86_64::memory + +#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP |
