aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86_64/CMakeLists.txt1
-rw-r--r--arch/x86_64/include/arch/memory/frame_allocator.hpp117
-rw-r--r--arch/x86_64/include/arch/memory/multiboot.hpp2
-rw-r--r--arch/x86_64/include/arch/memory/paging.hpp150
-rw-r--r--arch/x86_64/include/arch/video/vga/io.hpp8
-rw-r--r--arch/x86_64/include/arch/video/vga/text.hpp32
-rw-r--r--arch/x86_64/src/kernel/main.cpp26
-rw-r--r--arch/x86_64/src/memory/frame_allocator.cpp35
-rw-r--r--arch/x86_64/src/memory/multiboot.cpp28
-rw-r--r--arch/x86_64/src/memory/paging.cpp53
10 files changed, 328 insertions, 124 deletions
diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt
index 882ea9a..25f8634 100644
--- a/arch/x86_64/CMakeLists.txt
+++ b/arch/x86_64/CMakeLists.txt
@@ -43,6 +43,7 @@ target_sources("_video" PRIVATE
target_sources("_memory" PRIVATE
"src/memory/multiboot.cpp"
"src/memory/frame_allocator.cpp"
+ "src/memory/paging.cpp"
)
#[============================================================================[
diff --git a/arch/x86_64/include/arch/memory/frame_allocator.hpp b/arch/x86_64/include/arch/memory/frame_allocator.hpp
index 1fd1f08..ab93231 100644
--- a/arch/x86_64/include/arch/memory/frame_allocator.hpp
+++ b/arch/x86_64/include/arch/memory/frame_allocator.hpp
@@ -8,47 +8,46 @@
namespace teachos::arch::memory
{
- namespace
- {
- constexpr std::size_t PAGE_FRAME_SIZE = 4096U; ///< Default page size of x86_84 is always 4KiB
- }
+ constexpr std::size_t PAGE_FRAME_SIZE = 4096U; ///< Default page size of x86_84 is always 4KiB.
/**
- * @brief Specific frame containing helper functions to determine if a specific address is in that frame or not
+ * @brief Specific physical_frame containing helper functions to determine if a specific address is in that
+ * physical_frame or not.
*/
- struct frame
+ struct physical_frame
{
/**
* @brief Constructor
*
- * @param frame_number Index number that should be assigned to this frame
+ * @param frame_number Index number that should be assigned to this physical_frame.
*/
- frame(std::size_t frame_number);
+ explicit physical_frame(std::size_t frame_number);
/**
- * @brief Returns the frame the given address is contained in
+ * @brief Returns the physical_frame the given address is contained in.
*
- * @param address Address we want to get the corresponding frame for
- * @return Frame the given address is contained in
+ * @param address Address we want to get the corresponding physical_frame for.
+ * @return Frame the given address is contained in.
*/
- static auto containing_address(std::size_t address) -> frame;
+ static auto containing_address(std::size_t address) -> physical_frame;
/**
- * @brief Defaulted equals operator
+ * @brief Defaulted equals operator.
*/
- constexpr auto operator==(const frame & other) const -> bool = default;
+ constexpr auto operator==(const physical_frame & other) const -> bool = default;
/**
- * @brief Defaulted three-way comparsion operator
+ * @brief Defaulted three-way comparsion operator.
*/
- constexpr auto operator<=>(const frame & other) const -> std::partial_ordering = default;
+ constexpr auto operator<=>(const physical_frame & other) const -> std::partial_ordering = default;
- std::size_t frame_number; ///< Index number of the current frame, used to distinguish it from other frames
+ std::size_t
+ frame_number; ///< Index number of the current physical frame, used to distinguish it from other frames.
};
template<typename T>
concept FrameAllocator = requires(T t) {
- { t.allocate_frame() } -> std::same_as<std::optional<frame>>;
+ { t.allocate_frame() } -> std::same_as<std::optional<physical_frame>>;
{ t.deallocate_frame() } -> std::same_as<void>;
};
@@ -58,121 +57,121 @@ namespace teachos::arch::memory
struct memory_area_iterator
{
/**
- * @brief Constructor
+ * @brief Constructor.
*
- * @param p Underlying address the iterator should point too, ensure to not pass an invalid pointer
+ * @param p Underlying address the iterator should point too, ensure to not pass an invalid pointer.
*/
explicit memory_area_iterator(memory_area * p);
/**
* @brief Dereferences the initally given pointer to its value.
*
- * @return Reference to the value
+ * @return Reference to the value.
*/
memory_area & operator*() const;
/**
* @brief Post increment operator. Returns a copy of the value
*
- * @return Copy of the incremented underlying address
+ * @return Copy of the incremented underlying address.
*/
memory_area_iterator operator++(int);
/**
- * @brief Pre increment operator. Returns a reference to the changed value
+ * @brief Pre increment operator. Returns a reference to the changed value.
*
- * @return Reference to the incremented underlying address
+ * @return Reference to the incremented underlying address.
*/
memory_area_iterator & operator++();
/**
* @brief Defaulted comparsion operator. Simply compares the memory address of both iterators.
*
- * @param other Other iterator to compare to
- * @return Whether poith iterators point to the same underlying address in memory
+ * @param other Other iterator to compare to.
+ * @return Whether poith iterators point to the same underlying address in memory.
*/
bool operator==(memory_area_iterator const & other) const = default;
private:
- memory_area * ptr; ///< Underlying address the iterator is currently pointing too
+ memory_area * ptr; ///< Underlying address the iterator is currently pointing too.
};
/**
- * @brief Allocates memory using memory areas read from the multiboot2 information pointer
+ * @brief Allocates memory using memory areas read from the multiboot2 information pointer.
*/
struct area_frame_allocator
{
/**
* @brief Constructor
*
- * @param kernel_start Start address of the kernel code in memory
- * @param kernel_end End address of the kernel code in memory
- * @param multiboot_start Start address of the multiboot code in memory
- * @param multiboot_end End address of the multiboot code in memory
- * @param memory_areas Pointer to the first element of all memory areas
- * @param area_count Amount of total entries in the memory_areas array
+ * @param kernel_start Start address of the kernel code in memory.
+ * @param kernel_end End address of the kernel code in memory.
+ * @param multiboot_start Start address of the multiboot code in memory.
+ * @param multiboot_end End address of the multiboot code in memory.
+ * @param memory_areas Pointer to the first element of all memory areas.
+ * @param area_count Amount of total entries in the memory_areas array.
*/
area_frame_allocator(std::size_t kernel_start, std::size_t kernel_end, std::size_t multiboot_start,
std::size_t multiboot_end, memory_area * memory_areas, uint8_t area_count)
: area_begin(memory_areas)
, area_end(memory_areas + area_count)
- , kernel_start(frame::containing_address(kernel_start))
- , kernel_end(frame::containing_address(kernel_end))
- , multiboot_start(frame::containing_address(multiboot_start))
- , multiboot_end(frame::containing_address(multiboot_end))
+ , kernel_start(physical_frame::containing_address(kernel_start))
+ , kernel_end(physical_frame::containing_address(kernel_end))
+ , multiboot_start(physical_frame::containing_address(multiboot_start))
+ , multiboot_end(physical_frame::containing_address(multiboot_end))
{
choose_next_area();
}
/**
- * @brief Allocate memory by finding and returning a free frame
+ * @brief Allocate memory by finding and returning a free physical_frame.
*
- * The frame allocation executes multiple checks before returning
- * the frame that is available to allocate. It must at least
+ * 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 frame
+ * - update the next_free_frame after finding a free physical_frame
*/
- auto allocate_frame() -> std::optional<frame>;
+ auto allocate_frame() -> std::optional<physical_frame>;
/**
- * @brief Deallocates a previously allocated frame
+ * @brief Deallocates a previously allocated physical_frame.
*
- * @param frame Previously allocated frame that should be allocated
+ * @param physical_frame Previously allocated physical_frame that should be allocated.
*/
- auto deallocate_frame(frame frame) -> void;
+ auto deallocate_frame(physical_frame physical_frame) -> void;
/**
* @brief Returns the iterator pointing to the first element of the memory area.
- * Allows using this class in the for each loop, because it follows the InputIterator template scheme
+ * Allows using this class in the for each loop, because it follows the InputIterator template scheme.
*
- * @return Iterator pointing to first element of the memory area
+ * @return Iterator pointing to first element of the memory area.
*/
auto begin() -> memory_area_iterator;
/**
* @brief Returns the iterator pointing to one past the last element of the memory area.
- * Allows using this class in the for each loop, because it follows the InputIterator template scheme
+ * Allows using this class in the for each loop, because it follows the InputIterator template scheme.
*
- * @return Iterator pointing to one past the last element of the memory area
+ * @return Iterator pointing to one past the last element of the memory area.
*/
auto end() -> memory_area_iterator;
private:
/**
- * @brief Find the next memory area and write it into current_area
+ * @brief Find the next memory area and write it into current_area.
*/
auto choose_next_area() -> void;
- frame next_free_frame{0}; ///< The frame after the last allocated one
- std::optional<memory_area> current_area{std::nullopt}; ///< The current memory area
- memory_area_iterator area_begin; ///< Pointer to the first element of all memory areas
- memory_area_iterator area_end; ///< Pointer to one pas the last element of all memory areas
- frame const kernel_start; ///< The start address of the kernel code in memory
- frame const kernel_end; ///< The end address of the kernel code in memory
- frame const multiboot_start; ///< The start address of the multiboot code in memory
- frame const multiboot_end; ///< The end address of the multiboot code in memory
+ physical_frame next_free_frame{0}; ///< The physical_frame after the last allocated one.
+ std::optional<memory_area> current_area{std::nullopt}; ///< The current memory area.
+ memory_area_iterator area_begin; ///< Pointer to the first element of all memory areas.
+ memory_area_iterator area_end; ///< Pointer to one pas the last element of all memory areas.
+ physical_frame const kernel_start; ///< The start address of the kernel code in memory.
+ physical_frame const kernel_end; ///< The end address of the kernel code in memory.
+ physical_frame const multiboot_start; ///< The start address of the multiboot code in memory.
+ physical_frame const multiboot_end; ///< The end address of the multiboot code in memory.
};
} // namespace teachos::arch::memory
diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp
index 35b483e..93d214c 100644
--- a/arch/x86_64/include/arch/memory/multiboot.hpp
+++ b/arch/x86_64/include/arch/memory/multiboot.hpp
@@ -152,7 +152,7 @@ namespace teachos::arch::memory
*
* @return Current section is writable.
*/
- auto writeable() const -> bool;
+ auto writable() const -> bool;
/**
* @brief (SHF_ALLOC) Whether the current section occupies memory during execution or not. ALLOC flag is shown in
diff --git a/arch/x86_64/include/arch/memory/paging.hpp b/arch/x86_64/include/arch/memory/paging.hpp
new file mode 100644
index 0000000..a5408e1
--- /dev/null
+++ b/arch/x86_64/include/arch/memory/paging.hpp
@@ -0,0 +1,150 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_HPP
+
+#include "frame_allocator.hpp"
+
+namespace teachos::arch::memory
+{
+ constexpr std::size_t PAGE_TABLE_ENTRY_COUNT = 512U; ///< Default entry count of a page table in x86_84 is 512.
+
+ /**
+ * @brief Virtual page entry contained in P1 page tables
+ */
+ struct virtual_page
+ {
+ std::size_t number; ///< Index number of the current virtual page, used to distinguish it from other pages.
+
+ /**
+ * @brief Defaulted equals operator.
+ */
+ constexpr auto operator==(const virtual_page & other) const -> bool = default;
+
+ /**
+ * @brief Defaulted three-way comparsion operator.
+ */
+ constexpr auto operator<=>(const virtual_page & other) const -> std::partial_ordering = default;
+ };
+
+ /**
+ * @brief Marks a specific entry in an actual page table.
+ */
+ struct entry
+ {
+ /**
+ * @brief Whether the current page is unused, meaning the underlying std::bitset is 0.
+ *
+ * @return Current page is in memory.
+ */
+ auto is_unused() const -> bool;
+
+ /**
+ * @brief Marks the page as unused, meaning the underlying std::bitset is set to 0.
+ */
+ auto set_unused() -> void;
+
+ /**
+ * @brief Whether the current page is in memory and therefore present or not. Read from bit index 0.
+ *
+ * @return Current page is in memory.
+ */
+ auto present() const -> bool;
+
+ /**
+ * @brief Whether it is possible to write to the current page or not. Read from bit index 1.
+ *
+ * @return Current page can be written too.
+ */
+ auto writable() const -> bool;
+
+ /**
+ * @brief Whether the current page can be accessed in user mode, or only in kernel mode code. Read from bit index 2.
+ *
+ * @return Current page can be accessed in user mode.
+ */
+ auto user_accessible() const -> bool;
+
+ /**
+ * @brief Whether any write to the current page go directly to memory instead of the cache or not. Read from bit
+ * index 3.
+ *
+ * @return Writes to the current page go directly to memory.
+ */
+ auto write_through_caching() const -> bool;
+
+ /**
+ * @brief Whether the current page uses caching or not. Read from bit index 4.
+ *
+ * @return Current page does not use caching.
+ */
+ auto disabled_caching() const -> bool;
+
+ /**
+ * @brief Whether the current page is currently being used or not. Read from bit index 5.
+ *
+ * @return Current page is currently being used.
+ */
+ auto is_accessing() const -> bool;
+
+ /**
+ * @brief Whether the current page has been writen too or not. Read from bit index 6.
+ *
+ * @return Current page has been writen too.
+ */
+ auto is_diry() const -> bool;
+
+ /**
+ * @brief Whether the current page is huge or not (2 MiB page size in P2 page table and 1 GiB in P3 page table,
+ * instead of 4 KiB). Has to be false for P1 and P4 page tables. Read from bit index 7.
+ *
+ * @return Current page is huge
+ */
+ auto is_huge_page() const -> bool;
+
+ /**
+ * @brief Whether the current page is not flushed from caches on address space switches or not (PGE bit of CR4
+ * register has to be set). Read from bit index 8.
+ *
+ * @return Current page is not flushed from caches on address space switches.
+ */
+ auto is_global() const -> bool;
+
+ /**
+ * @brief Whether the current page is forbidden from executing code or not (NXE bit in the EFER register has to be
+ * set). Read from bit index 63.
+ *
+ * @return Current page is forbidden from executing code.
+ */
+ auto executing_code_forbidden() const -> bool;
+
+ /**
+ * @brief Calculates the physical frame this entry is pointing too, can be null if the page is not present in
+ * memory.
+ *
+ * @return Calculated physical frame entry is pointing too.
+ */
+ auto calculate_pointed_to_frame() const -> std::optional<physical_frame>;
+
+ private:
+ /**
+ * @brief Extracts the physical address from the underlying bitset read from bit index 12 - 51. Is a 52 bit page
+ * aligned physical address of the frame of the next page table or the pyhscial address of the frame for P1 page
+ * tables.
+ *
+ * @return Extracted physical address of the next page or of the frame for P1 page tables.
+ */
+ auto calculate_physical_address() const -> std::size_t;
+
+ /**
+ * @brief Checks the underlying std::bitset if the bit at the specific index is set, meaning a value of 1
+ *
+ * @param index Specific index we want to check at
+ * @return Bit value 1 is set and will return true
+ */
+ auto is_bit_set(uint8_t index) const -> bool;
+
+ std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 9 - 11 and 52 - 62 can be freely
+ ///< used for additional flagsby the operating system.
+ };
+} // namespace teachos::arch::memory
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_HPP
diff --git a/arch/x86_64/include/arch/video/vga/io.hpp b/arch/x86_64/include/arch/video/vga/io.hpp
index da9375d..3d2e90c 100644
--- a/arch/x86_64/include/arch/video/vga/io.hpp
+++ b/arch/x86_64/include/arch/video/vga/io.hpp
@@ -10,24 +10,24 @@ namespace teachos::arch::video::vga
namespace crtc
{
/**
- * @brief The address port of the CRT Controller
+ * @brief The address port of the CRT Controller.
*/
using address_port = arch::io::port<0x3d4, 1>;
/**
- * @brief The data port of the CRT Controller
+ * @brief The data port of the CRT Controller.
*/
using data_port = arch::io::port<0x3d5, 1>;
namespace registers
{
/**
- * @brief The address of the Cursor Start register of the CRTC
+ * @brief The address of the Cursor Start register of the CRTC.
*/
[[maybe_unused]] auto constexpr cursor_start = std::byte{0x0a};
/**
- * @brief The address of the Cursor End register of the CRTC
+ * @brief The address of the Cursor End register of the CRTC.
*/
[[maybe_unused]] auto constexpr curser_end = std::byte{0x0b};
} // namespace registers
diff --git a/arch/x86_64/include/arch/video/vga/text.hpp b/arch/x86_64/include/arch/video/vga/text.hpp
index 79ec7be..cfafce0 100644
--- a/arch/x86_64/include/arch/video/vga/text.hpp
+++ b/arch/x86_64/include/arch/video/vga/text.hpp
@@ -12,14 +12,14 @@ namespace teachos::arch::video::vga::text
*/
enum struct color : std::uint8_t
{
- black, /**< Equivalent to HTML color \#000000 */
- blue, /**< Equivalent to HTML color \#0000AA */
- green, /**< Equivalent to HTML color \#00AA00 */
- cyan, /**< Equivalent to HTML color \#00AAAA */
- red, /**< Equivalent to HTML color \#AA0000 */
- purple, /**< Equivalent to HTML color \#AA00AA */
- brown, /**< Equivalent to HTML color \#AA5500 */
- gray, /**< Equivalent to HTML color \#AAAAAA */
+ black, ///< Equivalent to HTML color \#000000
+ blue, ///< Equivalent to HTML color \#0000AA
+ green, ///< Equivalent to HTML color \#00AA00
+ cyan, ///< Equivalent to HTML color \#00AAAA
+ red, ///< Equivalent to HTML color \#AA0000
+ purple, ///< Equivalent to HTML color \#AA00AA
+ brown, ///< Equivalent to HTML color \#AA5500
+ gray, ///< Equivalent to HTML color \#AAAAAA
};
/**
@@ -27,8 +27,8 @@ namespace teachos::arch::video::vga::text
*/
enum struct foreground_flag : bool
{
- none, /**< Apply no flag e.g., keep color as is. */
- intense, /**< Make the color more intense (usually brighter). */
+ none, ///< Apply no flag e.g., keep color as is.
+ intense, ///< Make the color more intense (usually brighter).
};
/**
@@ -36,8 +36,8 @@ namespace teachos::arch::video::vga::text
*/
enum struct background_flag : bool
{
- none, /**< Apply no flag e.g., keep color as is. */
- blink_or_bright, /**< Make the cell blink or more intense, dependent on the VGA configuration */
+ none, ///< Apply no flag e.g., keep color as is.
+ blink_or_bright, ///< Make the cell blink or more intense, dependent on the VGA configuration
};
/**
@@ -51,10 +51,10 @@ namespace teachos::arch::video::vga::text
*/
struct attribute
{
- color foreground_color : 3; /**< The foreground color of the cell, e.g. the color of the code point.*/
- enum foreground_flag foreground_flag : 1; /**< The foreground color modification flag of the cell.*/
- color bacground_color : 3; /**< The background color of the cell.*/
- enum background_flag background_flag : 1; /**< The background color modification flag of the cell.*/
+ color foreground_color : 3; ///< The foreground color of the cell, e.g. the color of the code point
+ enum foreground_flag foreground_flag : 1; ///< The foreground color modification flag of the cell.
+ color bacground_color : 3; ///< The background color of the cell.
+ enum background_flag background_flag : 1; ///< The background color modification flag of the cell.
};
static_assert(sizeof(attribute) == 1, "The VGA text mode attribute must fit inside a single byte.");
diff --git a/arch/x86_64/src/kernel/main.cpp b/arch/x86_64/src/kernel/main.cpp
index bdf530c..7e4a336 100644
--- a/arch/x86_64/src/kernel/main.cpp
+++ b/arch/x86_64/src/kernel/main.cpp
@@ -5,6 +5,8 @@
#include "arch/memory/multiboot.hpp"
#include "arch/video/vga/text.hpp"
+#include <algorithm>
+
namespace teachos::arch::kernel
{
auto assert(bool condition) -> void
@@ -63,7 +65,7 @@ namespace teachos::arch::kernel
for (auto section = begin; section != end; ++section)
{
- bool const writeable = section->flags.writeable();
+ bool const writable = section->flags.writable();
bool const occupies_memory = section->flags.occupies_memory();
bool const is_executable = section->flags.is_executable();
bool const contains_duplicate_data = section->flags.contains_duplicate_data();
@@ -79,7 +81,7 @@ namespace teachos::arch::kernel
bool const is_excluded_unless_referenced_or_allocated =
section->flags.is_excluded_unless_referenced_or_allocated();
- if (writeable && occupies_memory && is_executable && contains_duplicate_data && contains_strings &&
+ if (writable && occupies_memory && is_executable && contains_duplicate_data && contains_strings &&
section_header_info_is_section_header_table_index && preserve_ordering_after_combination &&
requires_special_os_processing && is_section_group_member && holds_thread_local_data && is_compressed &&
has_special_ordering_requirements && is_excluded_unless_referenced_or_allocated)
@@ -182,20 +184,16 @@ namespace teachos::arch::kernel
// Address of Frame: 0x203F00
auto allocator = arch::memory::area_frame_allocator(kernel_start, kernel_end, multiboot_start, multiboot_end,
memory_areas, area_count);
- auto allocated = allocator.allocate_frame();
// WATCH OUT: using optional::value() crashes the build... I think its because of missing exception handling
- if (allocated.has_value())
- {
- video::vga::text::write("Allocated Frame address: ", video::vga::text::common_attributes::green_on_black);
- video::vga::text::write_number(reinterpret_cast<uint64_t>(&allocated->frame_number),
- video::vga::text::common_attributes::green_on_black);
- video::vga::text::write("Allocated Frame number: ", video::vga::text::common_attributes::green_on_black);
- video::vga::text::write_number(allocated->frame_number, video::vga::text::common_attributes::green_on_black);
- }
- else
+ auto last_allocated = allocator.allocate_frame();
+ auto allocated = last_allocated;
+ do
{
- video::vga::text::write("NO VALUE", video::vga::text::common_attributes::green_on_black);
- }
+ last_allocated = allocated;
+ allocated = allocator.allocate_frame();
+ } while (allocated.has_value());
+ video::vga::text::write("Allocated Frames", video::vga::text::common_attributes::green_on_black);
+ video::vga::text::write_number(allocated->frame_number, video::vga::text::common_attributes::green_on_black);
}
} // namespace teachos::arch::kernel
diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp
index 3ad2d96..3733cc3 100644
--- a/arch/x86_64/src/memory/frame_allocator.cpp
+++ b/arch/x86_64/src/memory/frame_allocator.cpp
@@ -2,13 +2,16 @@
namespace teachos::arch::memory
{
- frame::frame(std::size_t frame_number)
+ physical_frame::physical_frame(std::size_t frame_number)
: frame_number(frame_number)
{
// Nothing to do
}
- auto frame::containing_address(std::size_t address) -> frame { return frame{address / PAGE_FRAME_SIZE}; }
+ auto physical_frame::containing_address(std::size_t address) -> physical_frame
+ {
+ return physical_frame{address / PAGE_FRAME_SIZE};
+ }
memory_area_iterator::memory_area_iterator(memory_area * p)
: ptr(p)
@@ -39,7 +42,7 @@ namespace teachos::arch::memory
memory_area & area = *it;
std::size_t address = area.base_address + area.area_length - 1;
- if (frame::containing_address(address) >= next_free_frame)
+ if (physical_frame::containing_address(address) >= next_free_frame)
{
// The `next_free_frame` address is smaller than the last address of the current area
if (!current_area || area.base_address < current_area->base_address)
@@ -52,7 +55,7 @@ namespace teachos::arch::memory
if (current_area)
{
// Update the `next_free_frame` according to the new memory area
- frame start_frame = frame::containing_address(current_area->base_address);
+ physical_frame start_frame = physical_frame::containing_address(current_area->base_address);
if (next_free_frame < start_frame)
{
next_free_frame = start_frame;
@@ -60,7 +63,7 @@ namespace teachos::arch::memory
}
}
- auto area_frame_allocator::allocate_frame() -> std::optional<frame>
+ auto area_frame_allocator::allocate_frame() -> std::optional<physical_frame>
{
/*
* Only try to allocate memory if current_area is not null, because
@@ -68,29 +71,29 @@ namespace teachos::arch::memory
*/
if (current_area)
{
- frame frame{next_free_frame.frame_number};
+ physical_frame physical_frame{next_free_frame.frame_number};
- struct frame current_area_last_frame = {
- frame::containing_address(current_area->base_address + current_area->area_length - 1)};
+ struct physical_frame current_area_last_frame = {
+ physical_frame::containing_address(current_area->base_address + current_area->area_length - 1)};
if (next_free_frame > current_area_last_frame)
{
// All frames of current area are used, switch to next area
choose_next_area();
}
- else if (frame >= multiboot_start && frame <= kernel_end)
+ else if (physical_frame >= multiboot_start && physical_frame <= kernel_end)
{
- // `frame` is used by the kernel or multiboot information structure
- next_free_frame = arch::memory::frame{kernel_end.frame_number + 1};
+ // `physical_frame` is used by the kernel or multiboot information structure
+ next_free_frame = arch::memory::physical_frame{kernel_end.frame_number + 1};
}
else
{
// Frame is unused, increment `next_free_frame` and return it
next_free_frame.frame_number += 1;
- return frame;
+ return physical_frame;
}
- // `frame` was not valid, try it again with the updated `next_free_frame`
+ // `physical_frame` was not valid, try it again with the updated `next_free_frame`
return allocate_frame();
}
@@ -98,10 +101,10 @@ namespace teachos::arch::memory
return std::nullopt;
}
- auto area_frame_allocator::deallocate_frame(frame frame) -> void
+ auto area_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void
{
- // TODO: Fix, simply done because compiler will complain if frame is unused and not compile
- if (frame.frame_number == 3)
+ // TODO: Fix, simply done because compiler will complain if physical_frame is unused and not compile
+ if (physical_frame.frame_number == 3)
{
}
}
diff --git a/arch/x86_64/src/memory/multiboot.cpp b/arch/x86_64/src/memory/multiboot.cpp
index 3f6248d..bd3b00b 100644
--- a/arch/x86_64/src/memory/multiboot.cpp
+++ b/arch/x86_64/src/memory/multiboot.cpp
@@ -2,35 +2,35 @@
namespace teachos::arch::memory
{
- auto elf_section_flags::writeable() const -> bool { return is_bit_set(0); }
+ auto elf_section_flags::writable() const -> bool { return is_bit_set(0U); }
- auto elf_section_flags::occupies_memory() const -> bool { return is_bit_set(1); }
+ auto elf_section_flags::occupies_memory() const -> bool { return is_bit_set(1U); }
- auto elf_section_flags::is_executable() const -> bool { return is_bit_set(2); }
+ auto elf_section_flags::is_executable() const -> bool { return is_bit_set(2U); }
- auto elf_section_flags::contains_duplicate_data() const -> bool { return is_bit_set(4); }
+ auto elf_section_flags::contains_duplicate_data() const -> bool { return is_bit_set(4U); }
- auto elf_section_flags::contains_strings() const -> bool { return is_bit_set(5); }
+ auto elf_section_flags::contains_strings() const -> bool { return is_bit_set(5U); }
- auto elf_section_flags::section_header_info_is_section_header_table_index() const -> bool { return is_bit_set(6); }
+ auto elf_section_flags::section_header_info_is_section_header_table_index() const -> bool { return is_bit_set(6U); }
- auto elf_section_flags::preserve_ordering_after_combination() const -> bool { return is_bit_set(7); }
+ auto elf_section_flags::preserve_ordering_after_combination() const -> bool { return is_bit_set(7U); }
- auto elf_section_flags::requires_special_os_processing() const -> bool { return is_bit_set(8); }
+ auto elf_section_flags::requires_special_os_processing() const -> bool { return is_bit_set(8U); }
- auto elf_section_flags::is_section_group_member() const -> bool { return is_bit_set(9); }
+ auto elf_section_flags::is_section_group_member() const -> bool { return is_bit_set(9U); }
- auto elf_section_flags::holds_thread_local_data() const -> bool { return is_bit_set(10); }
+ auto elf_section_flags::holds_thread_local_data() const -> bool { return is_bit_set(10U); }
- auto elf_section_flags::is_compressed() const -> bool { return is_bit_set(11); }
+ auto elf_section_flags::is_compressed() const -> bool { return is_bit_set(11U); }
- auto elf_section_flags::has_special_ordering_requirements() const -> bool { return is_bit_set(30); }
+ auto elf_section_flags::has_special_ordering_requirements() const -> bool { return is_bit_set(30U); }
- auto elf_section_flags::is_excluded_unless_referenced_or_allocated() const -> bool { return is_bit_set(31); }
+ auto elf_section_flags::is_excluded_unless_referenced_or_allocated() const -> bool { return is_bit_set(31U); }
auto elf_section_flags::operator==(elf_section_flags const & other) const -> bool { return flags == other.flags; }
- auto elf_section_flags::is_bit_set(uint8_t index) const -> bool { return flags[index] == 1; }
+ auto elf_section_flags::is_bit_set(uint8_t index) const -> bool { return flags[index] == 1U; }
auto elf_section_header::is_null() const -> bool
{
diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp
new file mode 100644
index 0000000..555357c
--- /dev/null
+++ b/arch/x86_64/src/memory/paging.cpp
@@ -0,0 +1,53 @@
+#include "arch/memory/paging.hpp"
+
+namespace teachos::arch::memory
+{
+ auto entry::is_unused() const -> bool { return flags == 0U; }
+
+ auto entry::set_unused() -> void { flags = 0U; }
+
+ auto entry::present() const -> bool { return is_bit_set(0U); }
+
+ auto entry::writable() const -> bool { return is_bit_set(1U); }
+
+ auto entry::user_accessible() const -> bool { return is_bit_set(2U); }
+
+ auto entry::write_through_caching() const -> bool { return is_bit_set(3U); }
+
+ auto entry::disabled_caching() const -> bool { return is_bit_set(4U); }
+
+ auto entry::is_accessing() const -> bool { return is_bit_set(5U); }
+
+ auto entry::is_diry() const -> bool { return is_bit_set(6U); }
+
+ auto entry::is_huge_page() const -> bool { return is_bit_set(7U); }
+
+ auto entry::is_global() const -> bool { return is_bit_set(8U); }
+
+ auto entry::executing_code_forbidden() const -> bool { return is_bit_set(63U); }
+
+ auto entry::calculate_pointed_to_frame() const -> std::optional<physical_frame>
+ {
+ if (present())
+ {
+ auto physical_address = calculate_physical_address();
+ return physical_frame::containing_address(physical_address);
+ }
+ return std::nullopt;
+ }
+
+ auto entry::calculate_physical_address() const -> std::size_t
+ {
+ constexpr std::size_t start_bit = 12U;
+ constexpr std::size_t end_bit = 51U;
+ size_t value = 0U;
+
+ for (auto i = start_bit; i < end_bit; i++)
+ {
+ value |= (flags[i] ? (1 << (i - start_bit)) : 0);
+ }
+ return value;
+ }
+
+ auto entry::is_bit_set(uint8_t index) const -> bool { return flags[index] == 1U; }
+} // namespace teachos::arch::memory