From 6288868ebd728720236d6a857df2658bff2d6547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 29 Sep 2024 07:02:25 +0000 Subject: Pass multiboot info to main function --- arch/x86_64/include/arch/kernel/main.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/kernel/main.hpp b/arch/x86_64/include/arch/kernel/main.hpp index 6961594..57b9b58 100644 --- a/arch/x86_64/include/arch/kernel/main.hpp +++ b/arch/x86_64/include/arch/kernel/main.hpp @@ -5,7 +5,7 @@ namespace teachos::arch::kernel { - auto main() -> void; + auto main(size_t multiboot_information_address) -> void; } #endif \ No newline at end of file -- cgit v1.2.3 From eeee7967c17704fee443a3b5b02d53a580f18b73 Mon Sep 17 00:00:00 2001 From: TheSoeren Date: Sun, 29 Sep 2024 08:52:28 +0000 Subject: use multiboot_information_pointer public variable --- arch/x86_64/include/arch/boot/multiboot.hpp | 14 ++++++++++++++ arch/x86_64/include/arch/boot/pointers.hpp | 2 +- arch/x86_64/include/arch/kernel/main.hpp | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 arch/x86_64/include/arch/boot/multiboot.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/multiboot.hpp b/arch/x86_64/include/arch/boot/multiboot.hpp new file mode 100644 index 0000000..c6fed55 --- /dev/null +++ b/arch/x86_64/include/arch/boot/multiboot.hpp @@ -0,0 +1,14 @@ +#include + +struct multiboot_tag +{ + uint32_t type; + uint32_t size; +}; + +struct multiboot_info +{ + uint32_t total_size; + uint32_t reserved; + struct multiboot_tag tags[1]; // TODO: Size 0 +}; \ No newline at end of file diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index dcd14fe..c7424e2 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -5,7 +5,7 @@ namespace teachos::arch::boot { - extern "C" std::byte const multiboot_information_pointer; + extern "C" size_t const multiboot_information_pointer; } // namespace teachos::arch::boot #endif \ No newline at end of file diff --git a/arch/x86_64/include/arch/kernel/main.hpp b/arch/x86_64/include/arch/kernel/main.hpp index 57b9b58..6961594 100644 --- a/arch/x86_64/include/arch/kernel/main.hpp +++ b/arch/x86_64/include/arch/kernel/main.hpp @@ -5,7 +5,7 @@ namespace teachos::arch::kernel { - auto main(size_t multiboot_information_address) -> void; + auto main() -> void; } #endif \ No newline at end of file -- cgit v1.2.3 From 8f91d0ef50e01440f7e6e9f4afa5887f6afefea1 Mon Sep 17 00:00:00 2001 From: TheSoeren Date: Sun, 29 Sep 2024 09:26:17 +0000 Subject: read basic mem info --- arch/x86_64/include/arch/boot/multiboot.hpp | 38 +++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/multiboot.hpp b/arch/x86_64/include/arch/boot/multiboot.hpp index c6fed55..9a0757e 100644 --- a/arch/x86_64/include/arch/boot/multiboot.hpp +++ b/arch/x86_64/include/arch/boot/multiboot.hpp @@ -10,5 +10,39 @@ struct multiboot_info { uint32_t total_size; uint32_t reserved; - struct multiboot_tag tags[1]; // TODO: Size 0 -}; \ No newline at end of file + /* + * field "tags" is an array of multiboot_tags, however the array is never + * being accessed by index and using an array definition with size 0 produces a compiler + * error. + */ + struct multiboot_tag tags; +}; + +/* + * Define all multiboot tag types to ther respective values + * The gnu boot information format is defined here: + * https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Boot-information-format + */ +#define MULTIBOOT_TAG_ALIGN 8 +#define MULTIBOOT_TAG_TYPE_END 0 +#define MULTIBOOT_TAG_TYPE_CMDLINE 1 +#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2 +#define MULTIBOOT_TAG_TYPE_MODULE 3 +#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4 +#define MULTIBOOT_TAG_TYPE_BOOTDEV 5 +#define MULTIBOOT_TAG_TYPE_MMAP 6 +#define MULTIBOOT_TAG_TYPE_VBE 7 +#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8 +#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9 +#define MULTIBOOT_TAG_TYPE_APM 10 +#define MULTIBOOT_TAG_TYPE_EFI32 11 +#define MULTIBOOT_TAG_TYPE_EFI64 12 +#define MULTIBOOT_TAG_TYPE_SMBIOS 13 +#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14 +#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15 +#define MULTIBOOT_TAG_TYPE_NETWORK 16 +#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17 +#define MULTIBOOT_TAG_TYPE_EFI_BS 18 +#define MULTIBOOT_TAG_TYPE_EFI32_IH 19 +#define MULTIBOOT_TAG_TYPE_EFI64_IH 20 +#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21 -- cgit v1.2.3 From d2e1c8ba686d7d4ab32eda91c2f532676e9b8acf Mon Sep 17 00:00:00 2001 From: TheSoeren Date: Sun, 29 Sep 2024 14:03:39 +0000 Subject: create write_number function --- arch/x86_64/include/arch/video/vga/text.hpp | 50 +++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/video/vga/text.hpp b/arch/x86_64/include/arch/video/vga/text.hpp index 1e584d6..97344da 100644 --- a/arch/x86_64/include/arch/video/vga/text.hpp +++ b/arch/x86_64/include/arch/video/vga/text.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace teachos::arch::video::vga::text { @@ -108,6 +109,55 @@ namespace teachos::arch::video::vga::text * @see vga::text::attribute */ auto write(std::string_view code_points, attribute attribute) -> void; + + /** + * @brief Write a single character to the VGA text buffer. + * + * @note This function also updates the text mode buffer pointer. + * + * @param code_point A code point to write to the VGA text mode buffer. + * @param attribute The attribute to apply to the written sequence of code points. + * @see vga::text::attribute + */ + auto write_char(char code_point, attribute attribute) -> void; + + // TODO: Move concepts to their own file/folder + template + concept Integral = std::is_integral_v; + + /** + * @brief Write a integral value to the VGA text buffer. + * + * @note This function also updates the text mode buffer pointer. + * + * @param code_points A integral value to write to the VGA text mode buffer. + * @param attribute The attribute to apply to the written sequence of code points. + * @see vga::text::attribute + */ + template + auto write_number(T value, attribute attribute) -> void + { + T current_value = value; + + T divisor = 1; + while (current_value > 9) + { + divisor *= 10; + current_value = current_value / 10; + } + + current_value = value; + while (divisor > 0) + { + uint8_t quotient = current_value / divisor; + char ascii_digit = quotient + '0'; + + write_char(ascii_digit, attribute); + current_value %= divisor; + + divisor /= 10; + } + } } // namespace teachos::arch::video::vga::text #endif \ No newline at end of file -- cgit v1.2.3 From 20a5e5377c0f8e0769d67a7928891597bc463e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 30 Sep 2024 11:32:56 +0000 Subject: Attempt to print memory map --- arch/x86_64/include/arch/boot/multiboot.hpp | 11 ++++++++++- arch/x86_64/include/arch/boot/pointers.hpp | 2 +- arch/x86_64/include/arch/io/port_io.hpp | 2 +- arch/x86_64/include/arch/kernel/main.hpp | 2 +- arch/x86_64/include/arch/video/vga/io.hpp | 4 +--- arch/x86_64/include/arch/video/vga/text.hpp | 3 +-- 6 files changed, 15 insertions(+), 9 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/multiboot.hpp b/arch/x86_64/include/arch/boot/multiboot.hpp index 9a0757e..4182a18 100644 --- a/arch/x86_64/include/arch/boot/multiboot.hpp +++ b/arch/x86_64/include/arch/boot/multiboot.hpp @@ -2,7 +2,8 @@ struct multiboot_tag { - uint32_t type; + uint16_t type; + uint16_t flags; uint32_t size; }; @@ -18,6 +19,14 @@ struct multiboot_info struct multiboot_tag tags; }; +struct memory_map_entry +{ + uint64_t base_addr; + uint64_t length; + uint32_t type; + uint32_t reserved; +}; + /* * Define all multiboot tag types to ther respective values * The gnu boot information format is defined here: diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index c7424e2..25800f4 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -8,4 +8,4 @@ namespace teachos::arch::boot extern "C" size_t const multiboot_information_pointer; } // namespace teachos::arch::boot -#endif \ No newline at end of file +#endif diff --git a/arch/x86_64/include/arch/io/port_io.hpp b/arch/x86_64/include/arch/io/port_io.hpp index 5b61f90..c0f1ef3 100644 --- a/arch/x86_64/include/arch/io/port_io.hpp +++ b/arch/x86_64/include/arch/io/port_io.hpp @@ -131,4 +131,4 @@ namespace teachos::arch::io } // namespace teachos::arch::io -#endif \ No newline at end of file +#endif diff --git a/arch/x86_64/include/arch/kernel/main.hpp b/arch/x86_64/include/arch/kernel/main.hpp index 6961594..6759eb2 100644 --- a/arch/x86_64/include/arch/kernel/main.hpp +++ b/arch/x86_64/include/arch/kernel/main.hpp @@ -8,4 +8,4 @@ namespace teachos::arch::kernel auto main() -> void; } -#endif \ No newline at end of file +#endif diff --git a/arch/x86_64/include/arch/video/vga/io.hpp b/arch/x86_64/include/arch/video/vga/io.hpp index 9226c5c..da9375d 100644 --- a/arch/x86_64/include/arch/video/vga/io.hpp +++ b/arch/x86_64/include/arch/video/vga/io.hpp @@ -7,10 +7,8 @@ namespace teachos::arch::video::vga { - namespace crtc { - /** * @brief The address port of the CRT Controller */ @@ -38,4 +36,4 @@ namespace teachos::arch::video::vga } // namespace teachos::arch::video::vga -#endif \ No newline at end of file +#endif diff --git a/arch/x86_64/include/arch/video/vga/text.hpp b/arch/x86_64/include/arch/video/vga/text.hpp index 97344da..3b484e5 100644 --- a/arch/x86_64/include/arch/video/vga/text.hpp +++ b/arch/x86_64/include/arch/video/vga/text.hpp @@ -138,8 +138,8 @@ namespace teachos::arch::video::vga::text auto write_number(T value, attribute attribute) -> void { T current_value = value; - T divisor = 1; + while (current_value > 9) { divisor *= 10; @@ -154,7 +154,6 @@ namespace teachos::arch::video::vga::text write_char(ascii_digit, attribute); current_value %= divisor; - divisor /= 10; } } -- cgit v1.2.3 From b8e58d2f64fbb171b8687b9dd104ddd22fe4fc8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 1 Oct 2024 07:42:09 +0000 Subject: Adjust printing of memory map --- arch/x86_64/include/arch/boot/multiboot.hpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/multiboot.hpp b/arch/x86_64/include/arch/boot/multiboot.hpp index 4182a18..c39081a 100644 --- a/arch/x86_64/include/arch/boot/multiboot.hpp +++ b/arch/x86_64/include/arch/boot/multiboot.hpp @@ -2,8 +2,7 @@ struct multiboot_tag { - uint16_t type; - uint16_t flags; + uint32_t type; uint32_t size; }; @@ -27,6 +26,14 @@ struct memory_map_entry uint32_t reserved; }; +struct memory_map_info +{ + multiboot_tag tag; + uint32_t entry_size; + uint32_t entry_version; + struct memory_map_entry entries; +}; + /* * Define all multiboot tag types to ther respective values * The gnu boot information format is defined here: -- cgit v1.2.3 From e90fcb84fa43773d1e48bd82ce08381c6549a9cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 1 Oct 2024 08:22:40 +0000 Subject: Added efl section print method --- arch/x86_64/include/arch/boot/multiboot.hpp | 40 ++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/multiboot.hpp b/arch/x86_64/include/arch/boot/multiboot.hpp index c39081a..dfb289d 100644 --- a/arch/x86_64/include/arch/boot/multiboot.hpp +++ b/arch/x86_64/include/arch/boot/multiboot.hpp @@ -11,9 +11,9 @@ struct multiboot_info uint32_t total_size; uint32_t reserved; /* - * field "tags" is an array of multiboot_tags, however the array is never - * being accessed by index and using an array definition with size 0 produces a compiler - * error. + * field "tags" is an array of multiboot_tag, however the array is never + * being accessed by index we don't know the real size at compile-time, + * and using an array definition with size 0 produces a compiler error. */ struct multiboot_tag tags; }; @@ -22,6 +22,11 @@ struct memory_map_entry { uint64_t base_addr; uint64_t length; +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 +#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 +#define MULTIBOOT_MEMORY_NVS 4 +#define MULTIBOOT_MEMORY_BADRAM 5 uint32_t type; uint32_t reserved; }; @@ -31,9 +36,38 @@ struct memory_map_info multiboot_tag tag; uint32_t entry_size; uint32_t entry_version; + /* + * field "entries" is an array of memory_map_entry, however the array is never + * being accessed by index, we don't know the real size at compile-time, + * and using an array definition with size 0 produces a compiler error. + */ struct memory_map_entry entries; }; +struct elf64_section_header +{ + uint32_t sh_name; + uint32_t sh_type; + uint64_t sh_flags; + uint64_t sh_addr; + uint64_t sh_offset; + uint64_t sh_size; + uint32_t sh_link; + uint32_t sh_info; + uint64_t sh_addralign; + uint64_t sh_entsize; +}; + +struct elf_symbols_section +{ + multiboot_tag tag; + uint16_t num; + uint16_t entsize; + uint16_t shndx; + uint16_t reserved; + struct elf64_section_header sections; +}; + /* * Define all multiboot tag types to ther respective values * The gnu boot information format is defined here: -- cgit v1.2.3 From 4c60bad3150b07e973eb385613a90ebb8c94ecac Mon Sep 17 00:00:00 2001 From: TheSoeren Date: Tue, 1 Oct 2024 11:59:40 +0000 Subject: add structs, clean mip code --- arch/x86_64/include/arch/boot/multiboot.hpp | 86 +++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 12 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/multiboot.hpp b/arch/x86_64/include/arch/boot/multiboot.hpp index dfb289d..d3787f2 100644 --- a/arch/x86_64/include/arch/boot/multiboot.hpp +++ b/arch/x86_64/include/arch/boot/multiboot.hpp @@ -6,6 +6,14 @@ struct multiboot_tag uint32_t size; }; +struct basic_memory_info +{ + uint32_t type; + uint32_t size; + uint32_t mem_lower; + uint32_t mem_upper; +}; + struct multiboot_info { uint32_t total_size; @@ -44,18 +52,72 @@ struct memory_map_info struct memory_map_entry entries; }; -struct elf64_section_header +#define EI_NIDENT 16 + +/* ELF standard typedefs (yet more proof that was way overdue) */ +typedef uint16_t Elf64_Half; +typedef int16_t Elf64_SHalf; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +typedef uint64_t Elf64_Off; +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Section; + +struct executable_header +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf64_Half e_type; /* Object file type */ + Elf64_Half e_machine; /* Architecture */ + Elf64_Word e_version; /* Object file version */ + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; /* Processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size in bytes */ + Elf64_Half e_phentsize; /* Program header table entry size */ + Elf64_Half e_phnum; /* Program header table entry count */ + Elf64_Half e_shentsize; /* Section header table entry size */ + Elf64_Half e_shnum; /* Section header table entry count */ + Elf64_Half e_shstrndx; /* Section header string table index */ +}; + +struct program_header +{ + Elf64_Word p_type; /* Segment type */ + Elf64_Word p_flags; /* Segment flags */ + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment */ +}; + +struct elf_section_header +{ + Elf64_Word sh_name; /* Section name (string tbl index) */ + Elf64_Word sh_type; /* Section type */ + Elf64_Xword sh_flags; /* Section flags */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Section size in bytes */ + Elf64_Word sh_link; /* Link to another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +}; + +struct elf_symbol { - uint32_t sh_name; - uint32_t sh_type; - uint64_t sh_flags; - uint64_t sh_addr; - uint64_t sh_offset; - uint64_t sh_size; - uint32_t sh_link; - uint32_t sh_info; - uint64_t sh_addralign; - uint64_t sh_entsize; + Elf64_Word st_name; /* Symbol name (string tbl index) */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf64_Section st_shndx; /* Section index */ + Elf64_Addr st_value; /* Symbol value */ + Elf64_Xword st_size; /* Symbol size */ }; struct elf_symbols_section @@ -65,7 +127,7 @@ struct elf_symbols_section uint16_t entsize; uint16_t shndx; uint16_t reserved; - struct elf64_section_header sections; + struct elf_section_header sections; }; /* -- cgit v1.2.3 From 32add45849744dc976c7af6ec24f985bbace47d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 2 Oct 2024 13:02:35 +0000 Subject: Creating base frame allocation code --- arch/x86_64/include/arch/kernel/main.hpp | 2 - .../x86_64/include/arch/memory/frame_allocator.hpp | 48 ++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 arch/x86_64/include/arch/memory/frame_allocator.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/kernel/main.hpp b/arch/x86_64/include/arch/kernel/main.hpp index 6759eb2..8813b46 100644 --- a/arch/x86_64/include/arch/kernel/main.hpp +++ b/arch/x86_64/include/arch/kernel/main.hpp @@ -1,8 +1,6 @@ #ifndef TEACHOS_ARCH_X86_64_KERNEL_MAIN_HPP #define TEACHOS_ARCH_X86_64_KERNEL_MAIN_HPP -#include - namespace teachos::arch::kernel { auto main() -> void; diff --git a/arch/x86_64/include/arch/memory/frame_allocator.hpp b/arch/x86_64/include/arch/memory/frame_allocator.hpp new file mode 100644 index 0000000..bcb0882 --- /dev/null +++ b/arch/x86_64/include/arch/memory/frame_allocator.hpp @@ -0,0 +1,48 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_FRAME_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_FRAME_HPP + +#include +#include + +namespace teachos::arch::memory +{ + namespace + { + const size_t PAGE_FRAME_SIZE = 4096U; + } + + struct Frame + { + size_t frame_number; + + Frame(size_t frame_number) + : frame_number(frame_number) + { + // Nothing to do + } + + auto containing_address(size_t address) -> Frame { return Frame{address / PAGE_FRAME_SIZE}; } + }; + + struct IFrameAllocator + { + virtual auto allocate_frame() -> std::optional = 0; + virtual auto deallocate_frame(Frame frame) -> void = 0; + }; + + struct AreaFrameAllocator : public IFrameAllocator + { + Frame next_free_frame; + // std::optional current_area; + // MemoryArea * areas; + Frame kernel_start; + Frame kernel_end; + Frame multiboot_start; + Frame multiboot_end; + + auto allocate_frame() -> std::optional override; + auto deallocate_frame(Frame frame) -> void override; + }; +} // namespace teachos::arch::memory + +#endif // TEACHOS_ARCH_X86_64_MEMORY_FRAME_HPP -- cgit v1.2.3 From c2c7ad21fdd42111180d317ef50b15b7404769d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 2 Oct 2024 13:32:28 +0000 Subject: Improve naming, add enums and move into namespace --- arch/x86_64/include/arch/boot/multiboot.hpp | 160 ----------------------- arch/x86_64/include/arch/memory/multiboot.hpp | 174 ++++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 160 deletions(-) delete mode 100644 arch/x86_64/include/arch/boot/multiboot.hpp create mode 100644 arch/x86_64/include/arch/memory/multiboot.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/multiboot.hpp b/arch/x86_64/include/arch/boot/multiboot.hpp deleted file mode 100644 index d3787f2..0000000 --- a/arch/x86_64/include/arch/boot/multiboot.hpp +++ /dev/null @@ -1,160 +0,0 @@ -#include - -struct multiboot_tag -{ - uint32_t type; - uint32_t size; -}; - -struct basic_memory_info -{ - uint32_t type; - uint32_t size; - uint32_t mem_lower; - uint32_t mem_upper; -}; - -struct multiboot_info -{ - uint32_t total_size; - uint32_t reserved; - /* - * field "tags" is an array of multiboot_tag, however the array is never - * being accessed by index we don't know the real size at compile-time, - * and using an array definition with size 0 produces a compiler error. - */ - struct multiboot_tag tags; -}; - -struct memory_map_entry -{ - uint64_t base_addr; - uint64_t length; -#define MULTIBOOT_MEMORY_AVAILABLE 1 -#define MULTIBOOT_MEMORY_RESERVED 2 -#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 -#define MULTIBOOT_MEMORY_NVS 4 -#define MULTIBOOT_MEMORY_BADRAM 5 - uint32_t type; - uint32_t reserved; -}; - -struct memory_map_info -{ - multiboot_tag tag; - uint32_t entry_size; - uint32_t entry_version; - /* - * field "entries" is an array of memory_map_entry, however the array is never - * being accessed by index, we don't know the real size at compile-time, - * and using an array definition with size 0 produces a compiler error. - */ - struct memory_map_entry entries; -}; - -#define EI_NIDENT 16 - -/* ELF standard typedefs (yet more proof that was way overdue) */ -typedef uint16_t Elf64_Half; -typedef int16_t Elf64_SHalf; -typedef uint32_t Elf64_Word; -typedef int32_t Elf64_Sword; -typedef uint64_t Elf64_Xword; -typedef int64_t Elf64_Sxword; - -typedef uint64_t Elf64_Off; -typedef uint64_t Elf64_Addr; -typedef uint16_t Elf64_Section; - -struct executable_header -{ - unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ - Elf64_Half e_type; /* Object file type */ - Elf64_Half e_machine; /* Architecture */ - Elf64_Word e_version; /* Object file version */ - Elf64_Addr e_entry; /* Entry point virtual address */ - Elf64_Off e_phoff; /* Program header table file offset */ - Elf64_Off e_shoff; /* Section header table file offset */ - Elf64_Word e_flags; /* Processor-specific flags */ - Elf64_Half e_ehsize; /* ELF header size in bytes */ - Elf64_Half e_phentsize; /* Program header table entry size */ - Elf64_Half e_phnum; /* Program header table entry count */ - Elf64_Half e_shentsize; /* Section header table entry size */ - Elf64_Half e_shnum; /* Section header table entry count */ - Elf64_Half e_shstrndx; /* Section header string table index */ -}; - -struct program_header -{ - Elf64_Word p_type; /* Segment type */ - Elf64_Word p_flags; /* Segment flags */ - Elf64_Off p_offset; /* Segment file offset */ - Elf64_Addr p_vaddr; /* Segment virtual address */ - Elf64_Addr p_paddr; /* Segment physical address */ - Elf64_Xword p_filesz; /* Segment size in file */ - Elf64_Xword p_memsz; /* Segment size in memory */ - Elf64_Xword p_align; /* Segment alignment */ -}; - -struct elf_section_header -{ - Elf64_Word sh_name; /* Section name (string tbl index) */ - Elf64_Word sh_type; /* Section type */ - Elf64_Xword sh_flags; /* Section flags */ - Elf64_Addr sh_addr; /* Section virtual addr at execution */ - Elf64_Off sh_offset; /* Section file offset */ - Elf64_Xword sh_size; /* Section size in bytes */ - Elf64_Word sh_link; /* Link to another section */ - Elf64_Word sh_info; /* Additional section information */ - Elf64_Xword sh_addralign; /* Section alignment */ - Elf64_Xword sh_entsize; /* Entry size if section holds table */ -}; - -struct elf_symbol -{ - Elf64_Word st_name; /* Symbol name (string tbl index) */ - unsigned char st_info; /* Symbol type and binding */ - unsigned char st_other; /* Symbol visibility */ - Elf64_Section st_shndx; /* Section index */ - Elf64_Addr st_value; /* Symbol value */ - Elf64_Xword st_size; /* Symbol size */ -}; - -struct elf_symbols_section -{ - multiboot_tag tag; - uint16_t num; - uint16_t entsize; - uint16_t shndx; - uint16_t reserved; - struct elf_section_header sections; -}; - -/* - * Define all multiboot tag types to ther respective values - * The gnu boot information format is defined here: - * https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Boot-information-format - */ -#define MULTIBOOT_TAG_ALIGN 8 -#define MULTIBOOT_TAG_TYPE_END 0 -#define MULTIBOOT_TAG_TYPE_CMDLINE 1 -#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2 -#define MULTIBOOT_TAG_TYPE_MODULE 3 -#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4 -#define MULTIBOOT_TAG_TYPE_BOOTDEV 5 -#define MULTIBOOT_TAG_TYPE_MMAP 6 -#define MULTIBOOT_TAG_TYPE_VBE 7 -#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8 -#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9 -#define MULTIBOOT_TAG_TYPE_APM 10 -#define MULTIBOOT_TAG_TYPE_EFI32 11 -#define MULTIBOOT_TAG_TYPE_EFI64 12 -#define MULTIBOOT_TAG_TYPE_SMBIOS 13 -#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14 -#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15 -#define MULTIBOOT_TAG_TYPE_NETWORK 16 -#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17 -#define MULTIBOOT_TAG_TYPE_EFI_BS 18 -#define MULTIBOOT_TAG_TYPE_EFI32_IH 19 -#define MULTIBOOT_TAG_TYPE_EFI64_IH 20 -#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21 diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp new file mode 100644 index 0000000..95e6404 --- /dev/null +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -0,0 +1,174 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_HPP + +#include + +namespace teachos::arch::memory +{ + /* + * Define all multiboot tag types to ther respective values + * The gnu boot information format is defined here: + * https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Boot-information-format + */ + enum class MultibootTagType : uint32_t + { + END, + CMDLINE, + BOOT_LOADER_NAME, + MODULE, + BASIC_MEMORY_INFO, + BOOTDEV, + MEMORY_MAP, + VBE, + FRAMEBUFFER, + ELF_SECTIONS, + APM, + EFI32, + EFI64, + SMBIOS, + ACPI_OLD, + ACPI_NEW, + NETWORK, + EFI_MEMORY_MAP, + EFI_BS, + EFI32_IH, + EFI64_IH, + LOAD_BASE_ADDRESS + }; + + struct MultibootTag + { + MultibootTagType type; + uint32_t size; + }; + + struct MemoryInfo + { + uint32_t type; + uint32_t size; + uint32_t mem_lower; + uint32_t mem_upper; + }; + + struct MultibootInfo + { + uint32_t total_size; + uint32_t reserved; + /* + * field "tags" is an array of MultibootTag, however the array is never + * being accessed by index we don't know the real size at compile-time, + * and using an array definition with size 0 produces a compiler error. + */ + struct MultibootTag tags; + }; + + enum class MemoryAreaType : uint32_t + { + AVAILABLE = 1, + RESERVED, + ACPI_AVAILABLE, + RESERVED_HIBERNATION, + DEFECTIVE + }; + + struct MemoryArea + { + uint64_t base_addr; + uint64_t length; + MemoryAreaType type; + uint32_t reserved; + }; + + struct MemoryMap + { + MultibootTag tag; + uint32_t entry_size; + uint32_t entry_version; + /* + * field "entries" is an array of MemoryArea, however the array is never + * being accessed by index, we don't know the real size at compile-time, + * and using an array definition with size 0 produces a compiler error. + */ + struct MemoryArea entries; + }; + +#define EI_NIDENT 16 + + /* ELF standard typedefs (yet more proof that was way overdue) */ + typedef uint16_t Elf64_Half; + typedef int16_t Elf64_SHalf; + typedef uint32_t Elf64_Word; + typedef int32_t Elf64_Sword; + typedef uint64_t Elf64_Xword; + typedef int64_t Elf64_Sxword; + + typedef uint64_t Elf64_Off; + typedef uint64_t Elf64_Addr; + typedef uint16_t Elf64_Section; + + struct executable_header + { + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf64_Half e_type; /* Object file type */ + Elf64_Half e_machine; /* Architecture */ + Elf64_Word e_version; /* Object file version */ + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; /* Processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size in bytes */ + Elf64_Half e_phentsize; /* Program header table entry size */ + Elf64_Half e_phnum; /* Program header table entry count */ + Elf64_Half e_shentsize; /* Section header table entry size */ + Elf64_Half e_shnum; /* Section header table entry count */ + Elf64_Half e_shstrndx; /* Section header string table index */ + }; + + struct program_header + { + Elf64_Word p_type; /* Segment type */ + Elf64_Word p_flags; /* Segment flags */ + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment */ + }; + + struct elf_section_header + { + Elf64_Word sh_name; /* Section name (string tbl index) */ + Elf64_Word sh_type; /* Section type */ + Elf64_Xword sh_flags; /* Section flags */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Section size in bytes */ + Elf64_Word sh_link; /* Link to another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ + }; + + struct elf_symbol + { + Elf64_Word st_name; /* Symbol name (string tbl index) */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf64_Section st_shndx; /* Section index */ + Elf64_Addr st_value; /* Symbol value */ + Elf64_Xword st_size; /* Symbol size */ + }; + + struct elf_symbols_section + { + MultibootTag tag; + uint16_t num; + uint16_t entsize; + uint16_t shndx; + uint16_t reserved; + struct elf_section_header sections; + }; +} // namespace teachos::arch::memory + +#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_HPP -- cgit v1.2.3 From 1ab9c3c09d32283b39ca1026a9e29ada5ff7fda5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 6 Oct 2024 07:34:30 +0000 Subject: Renaming scheme --- .../x86_64/include/arch/memory/frame_allocator.hpp | 34 +++++++++++----------- arch/x86_64/include/arch/memory/multiboot.hpp | 30 +++++++++---------- arch/x86_64/include/arch/video/vga/text.hpp | 2 +- 3 files changed, 33 insertions(+), 33 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/frame_allocator.hpp b/arch/x86_64/include/arch/memory/frame_allocator.hpp index bcb0882..8dee848 100644 --- a/arch/x86_64/include/arch/memory/frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/frame_allocator.hpp @@ -11,37 +11,37 @@ namespace teachos::arch::memory const size_t PAGE_FRAME_SIZE = 4096U; } - struct Frame + struct frame { size_t frame_number; - Frame(size_t frame_number) + frame(size_t frame_number) : frame_number(frame_number) { // Nothing to do } - auto containing_address(size_t address) -> Frame { return Frame{address / PAGE_FRAME_SIZE}; } + auto containing_address(size_t address) -> frame { return frame{address / PAGE_FRAME_SIZE}; } }; - struct IFrameAllocator + struct frame_allocator { - virtual auto allocate_frame() -> std::optional = 0; - virtual auto deallocate_frame(Frame frame) -> void = 0; + virtual auto allocate_frame() -> std::optional = 0; + virtual auto deallocate_frame(frame frame) -> void = 0; }; - struct AreaFrameAllocator : public IFrameAllocator + struct area_frame_allocator : public frame_allocator { - Frame next_free_frame; - // std::optional current_area; - // MemoryArea * areas; - Frame kernel_start; - Frame kernel_end; - Frame multiboot_start; - Frame multiboot_end; - - auto allocate_frame() -> std::optional override; - auto deallocate_frame(Frame frame) -> void override; + frame next_free_frame; + // std::optional current_area; + // memory_area * areas; + frame kernel_start; + frame kernel_end; + frame multiboot_start; + frame multiboot_end; + + auto allocate_frame() -> std::optional override; + auto deallocate_frame(frame frame) -> void override; }; } // 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 95e6404..baad25b 100644 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -10,7 +10,7 @@ namespace teachos::arch::memory * The gnu boot information format is defined here: * https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Boot-information-format */ - enum class MultibootTagType : uint32_t + enum class multi_boot_tag_type : uint32_t { END, CMDLINE, @@ -36,13 +36,13 @@ namespace teachos::arch::memory LOAD_BASE_ADDRESS }; - struct MultibootTag + struct multi_boot_tag { - MultibootTagType type; + multi_boot_tag_type type; uint32_t size; }; - struct MemoryInfo + struct memory_info { uint32_t type; uint32_t size; @@ -50,19 +50,19 @@ namespace teachos::arch::memory uint32_t mem_upper; }; - struct MultibootInfo + struct multi_boot_info { uint32_t total_size; uint32_t reserved; /* - * field "tags" is an array of MultibootTag, however the array is never + * field "tags" is an array of multi_boot_tag, however the array is never * being accessed by index we don't know the real size at compile-time, * and using an array definition with size 0 produces a compiler error. */ - struct MultibootTag tags; + struct multi_boot_tag tags; }; - enum class MemoryAreaType : uint32_t + enum class memory_area_type : uint32_t { AVAILABLE = 1, RESERVED, @@ -71,25 +71,25 @@ namespace teachos::arch::memory DEFECTIVE }; - struct MemoryArea + struct memory_area { uint64_t base_addr; uint64_t length; - MemoryAreaType type; + memory_area_type type; uint32_t reserved; }; - struct MemoryMap + struct memory_map { - MultibootTag tag; + multi_boot_tag tag; uint32_t entry_size; uint32_t entry_version; /* - * field "entries" is an array of MemoryArea, however the array is never + * field "entries" is an array of memory_area, however the array is never * being accessed by index, we don't know the real size at compile-time, * and using an array definition with size 0 produces a compiler error. */ - struct MemoryArea entries; + struct memory_area entries; }; #define EI_NIDENT 16 @@ -162,7 +162,7 @@ namespace teachos::arch::memory struct elf_symbols_section { - MultibootTag tag; + multi_boot_tag tag; uint16_t num; uint16_t entsize; uint16_t shndx; diff --git a/arch/x86_64/include/arch/video/vga/text.hpp b/arch/x86_64/include/arch/video/vga/text.hpp index 3b484e5..9c4c701 100644 --- a/arch/x86_64/include/arch/video/vga/text.hpp +++ b/arch/x86_64/include/arch/video/vga/text.hpp @@ -130,7 +130,7 @@ namespace teachos::arch::video::vga::text * * @note This function also updates the text mode buffer pointer. * - * @param code_points A integral value to write to the VGA text mode buffer. + * @param value A integral value to write to the VGA text mode buffer. * @param attribute The attribute to apply to the written sequence of code points. * @see vga::text::attribute */ -- cgit v1.2.3 From 241c17a52e3954a6c1cf8d38f402d240070a5818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 6 Oct 2024 11:55:31 +0000 Subject: Use alignas instead of seperate variable in struct for padding --- arch/x86_64/include/arch/memory/multiboot.hpp | 41 ++------------------------- 1 file changed, 3 insertions(+), 38 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp index baad25b..a2d6e9d 100644 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -53,13 +53,12 @@ namespace teachos::arch::memory struct multi_boot_info { uint32_t total_size; - uint32_t reserved; /* * field "tags" is an array of multi_boot_tag, however the array is never * being accessed by index we don't know the real size at compile-time, * and using an array definition with size 0 produces a compiler error. */ - struct multi_boot_tag tags; + alignas(8) struct multi_boot_tag tags; }; enum class memory_area_type : uint32_t @@ -75,8 +74,7 @@ namespace teachos::arch::memory { uint64_t base_addr; uint64_t length; - memory_area_type type; - uint32_t reserved; + alignas(8) memory_area_type type; }; struct memory_map @@ -92,8 +90,6 @@ namespace teachos::arch::memory struct memory_area entries; }; -#define EI_NIDENT 16 - /* ELF standard typedefs (yet more proof that was way overdue) */ typedef uint16_t Elf64_Half; typedef int16_t Elf64_SHalf; @@ -106,36 +102,6 @@ namespace teachos::arch::memory typedef uint64_t Elf64_Addr; typedef uint16_t Elf64_Section; - struct executable_header - { - unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ - Elf64_Half e_type; /* Object file type */ - Elf64_Half e_machine; /* Architecture */ - Elf64_Word e_version; /* Object file version */ - Elf64_Addr e_entry; /* Entry point virtual address */ - Elf64_Off e_phoff; /* Program header table file offset */ - Elf64_Off e_shoff; /* Section header table file offset */ - Elf64_Word e_flags; /* Processor-specific flags */ - Elf64_Half e_ehsize; /* ELF header size in bytes */ - Elf64_Half e_phentsize; /* Program header table entry size */ - Elf64_Half e_phnum; /* Program header table entry count */ - Elf64_Half e_shentsize; /* Section header table entry size */ - Elf64_Half e_shnum; /* Section header table entry count */ - Elf64_Half e_shstrndx; /* Section header string table index */ - }; - - struct program_header - { - Elf64_Word p_type; /* Segment type */ - Elf64_Word p_flags; /* Segment flags */ - Elf64_Off p_offset; /* Segment file offset */ - Elf64_Addr p_vaddr; /* Segment virtual address */ - Elf64_Addr p_paddr; /* Segment physical address */ - Elf64_Xword p_filesz; /* Segment size in file */ - Elf64_Xword p_memsz; /* Segment size in memory */ - Elf64_Xword p_align; /* Segment alignment */ - }; - struct elf_section_header { Elf64_Word sh_name; /* Section name (string tbl index) */ @@ -166,8 +132,7 @@ namespace teachos::arch::memory uint16_t num; uint16_t entsize; uint16_t shndx; - uint16_t reserved; - struct elf_section_header sections; + alignas(8) struct elf_section_header sections; }; } // namespace teachos::arch::memory -- cgit v1.2.3 From b9c5aea495653bb9fc347fa6ba5976b42510af53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 6 Oct 2024 12:40:33 +0000 Subject: Added elf section type enum --- arch/x86_64/include/arch/memory/multiboot.hpp | 70 ++++++++++++++------------- 1 file changed, 37 insertions(+), 33 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp index a2d6e9d..c808213 100644 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -1,6 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_HPP #define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_HPP +#include #include namespace teachos::arch::memory @@ -90,48 +91,51 @@ namespace teachos::arch::memory struct memory_area entries; }; - /* ELF standard typedefs (yet more proof that was way overdue) */ - typedef uint16_t Elf64_Half; - typedef int16_t Elf64_SHalf; - typedef uint32_t Elf64_Word; - typedef int32_t Elf64_Sword; - typedef uint64_t Elf64_Xword; - typedef int64_t Elf64_Sxword; - - typedef uint64_t Elf64_Off; - typedef uint64_t Elf64_Addr; - typedef uint16_t Elf64_Section; - - struct elf_section_header + /** + * https://refspecs.linuxfoundation.org/LSB_2.1.0/LSB-Core-generic/LSB-Core-generic/elftypes.html + */ + enum class elf_section_type : uint32_t { - Elf64_Word sh_name; /* Section name (string tbl index) */ - Elf64_Word sh_type; /* Section type */ - Elf64_Xword sh_flags; /* Section flags */ - Elf64_Addr sh_addr; /* Section virtual addr at execution */ - Elf64_Off sh_offset; /* Section file offset */ - Elf64_Xword sh_size; /* Section size in bytes */ - Elf64_Word sh_link; /* Link to another section */ - Elf64_Word sh_info; /* Additional section information */ - Elf64_Xword sh_addralign; /* Section alignment */ - Elf64_Xword sh_entsize; /* Entry size if section holds table */ + INACTIVE, + PROGRAMM, + SYMBOL_TABLE, + STRING_TABLE, + RELOCATION_ENTRY_WITH_EXPLICIT_ADDENDS, + SYMBOL_HASH_TABLE, + DYNAMIC, + NOTE, + EMPTY, + RELOCATION_ENTRY_WITHOUT_EXPLICIT_ADDENDS, + UNSPECIFIED, + DYNAMIC_SYMBOL, + INITALIZATION_FUNCTION_ARRAY = 14, + TERMINATION_FUNCTION_ARRAY, + PRE_INITALIZATION_FUNCTION_ARRAY }; - struct elf_symbol + struct elf_section_header { - Elf64_Word st_name; /* Symbol name (string tbl index) */ - unsigned char st_info; /* Symbol type and binding */ - unsigned char st_other; /* Symbol visibility */ - Elf64_Section st_shndx; /* Section index */ - Elf64_Addr st_value; /* Symbol value */ - Elf64_Xword st_size; /* Symbol size */ + uint32_t sh_name; /* Section name (string tbl index) */ + elf_section_type sh_type; /* Section type */ + std::bitset<64U> sh_flags; /* Section flags */ + uint64_t sh_addr; /* Section virtual addr at execution */ + uint64_t sh_offset; /* Section file offset */ + uint64_t sh_size; /* Section size in bytes */ + uint32_t sh_link; /* Link to another section */ + uint32_t sh_info; /* Additional section information */ + uint64_t sh_addralign; /* Section alignment */ + uint64_t sh_entsize; /* Entry size if section holds table */ }; + /** + * https://gist.github.com/x0nu11byt3/bcb35c3de461e5fb66173071a2379779 + */ struct elf_symbols_section { multi_boot_tag tag; - uint16_t num; - uint16_t entsize; - uint16_t shndx; + uint32_t num; + uint32_t entsize; + uint32_t shndx; alignas(8) struct elf_section_header sections; }; } // namespace teachos::arch::memory -- cgit v1.2.3 From 951b314b655781dc59aee24cf952d03bf3b3ee83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 6 Oct 2024 13:32:14 +0000 Subject: Interpret files as bitset wrapper --- arch/x86_64/include/arch/memory/multiboot.hpp | 64 ++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 10 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp index c808213..f1f0613 100644 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -113,18 +113,62 @@ namespace teachos::arch::memory PRE_INITALIZATION_FUNCTION_ARRAY }; + /** + * https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html + */ + class elf_section_flags + { + public: + elf_section_flags(uint64_t flags) + : flags(flags) + { + // Nothing to do + } + + auto writeable() -> bool { return is_bit_set(0); } + + auto occupies_memory() -> bool { return is_bit_set(1); } + + auto is_executable() -> bool { return is_bit_set(2); } + + auto contains_duplicate_data() -> bool { return is_bit_set(4); } + + auto contains_strings() -> bool { return is_bit_set(5); } + + auto section_header_info_is_section_header_table_index() -> bool { return is_bit_set(6); } + + auto preserve_ordering_after_combination() -> bool { return is_bit_set(7); } + + auto requires_special_os_processing() -> bool { return is_bit_set(8); } + + auto is_section_group_member() -> bool { return is_bit_set(9); } + + auto holds_thread_local_data() -> bool { return is_bit_set(10); } + + auto is_compressed() -> bool { return is_bit_set(11); } + + auto has_special_ordering_requirements() -> bool { return is_bit_set(30); } + + auto is_excluded_unless_referenced_or_allocated() -> bool { return is_bit_set(31); } + + private: + auto is_bit_set(uint8_t index) -> bool { return flags[index] == 1; } + + std::bitset<64U> flags; + }; + struct elf_section_header { - uint32_t sh_name; /* Section name (string tbl index) */ - elf_section_type sh_type; /* Section type */ - std::bitset<64U> sh_flags; /* Section flags */ - uint64_t sh_addr; /* Section virtual addr at execution */ - uint64_t sh_offset; /* Section file offset */ - uint64_t sh_size; /* Section size in bytes */ - uint32_t sh_link; /* Link to another section */ - uint32_t sh_info; /* Additional section information */ - uint64_t sh_addralign; /* Section alignment */ - uint64_t sh_entsize; /* Entry size if section holds table */ + uint32_t sh_name; /* Section name (string tbl index) */ + elf_section_type sh_type; /* Section type */ + elf_section_flags sh_flags; /* Section flags */ + uint64_t sh_addr; /* Section virtual addr at execution */ + uint64_t sh_offset; /* Section file offset */ + uint64_t sh_size; /* Section size in bytes */ + uint32_t sh_link; /* Link to another section */ + uint32_t sh_info; /* Additional section information */ + uint64_t sh_addralign; /* Section alignment */ + uint64_t sh_entsize; /* Entry size if section holds table */ }; /** -- cgit v1.2.3 From 78153377d8a964d6b7290d966e5c1d30369abc2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 6 Oct 2024 13:40:24 +0000 Subject: Improve naming --- arch/x86_64/include/arch/memory/multiboot.hpp | 48 ++++++++++++++------------- 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp index f1f0613..37b10f0 100644 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -43,14 +43,6 @@ namespace teachos::arch::memory uint32_t size; }; - struct memory_info - { - uint32_t type; - uint32_t size; - uint32_t mem_lower; - uint32_t mem_upper; - }; - struct multi_boot_info { uint32_t total_size; @@ -62,6 +54,13 @@ namespace teachos::arch::memory alignas(8) struct multi_boot_tag tags; }; + struct memory_info + { + multi_boot_tag tag; + uint32_t mem_lower; + uint32_t mem_upper; + }; + enum class memory_area_type : uint32_t { AVAILABLE = 1, @@ -73,8 +72,8 @@ namespace teachos::arch::memory struct memory_area { - uint64_t base_addr; - uint64_t length; + uint64_t base_address; + uint64_t area_length; alignas(8) memory_area_type type; }; @@ -157,18 +156,21 @@ namespace teachos::arch::memory std::bitset<64U> flags; }; + /** + * https://docs.oracle.com/cd/E19455-01/806-3773/elf-2/index.html + */ struct elf_section_header { - uint32_t sh_name; /* Section name (string tbl index) */ - elf_section_type sh_type; /* Section type */ - elf_section_flags sh_flags; /* Section flags */ - uint64_t sh_addr; /* Section virtual addr at execution */ - uint64_t sh_offset; /* Section file offset */ - uint64_t sh_size; /* Section size in bytes */ - uint32_t sh_link; /* Link to another section */ - uint32_t sh_info; /* Additional section information */ - uint64_t sh_addralign; /* Section alignment */ - uint64_t sh_entsize; /* Entry size if section holds table */ + uint32_t name_table_index; + elf_section_type type; + elf_section_flags flags; + uint64_t virtual_address; + uint64_t file_offset; + uint64_t section_size; + uint32_t other_section; + uint32_t additional_information; + uint64_t address_alignment; + uint64_t fixed_table_entry_size; }; /** @@ -177,9 +179,9 @@ namespace teachos::arch::memory struct elf_symbols_section { multi_boot_tag tag; - uint32_t num; - uint32_t entsize; - uint32_t shndx; + uint32_t number_of_sections; + uint32_t entry_size; + uint32_t section_index; alignas(8) struct elf_section_header sections; }; } // namespace teachos::arch::memory -- cgit v1.2.3 From a6018f84cc8971859d90109740fbada8d77ff5a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 8 Oct 2024 07:58:53 +0000 Subject: Add more asserts for elf sections --- arch/x86_64/include/arch/memory/multiboot.hpp | 46 ++++++++++++++++++--------- 1 file changed, 31 insertions(+), 15 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp index 37b10f0..f6ff480 100644 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -124,40 +124,43 @@ namespace teachos::arch::memory // Nothing to do } - auto writeable() -> bool { return is_bit_set(0); } + auto writeable() const -> bool { return is_bit_set(0); } - auto occupies_memory() -> bool { return is_bit_set(1); } + auto occupies_memory() const -> bool { return is_bit_set(1); } - auto is_executable() -> bool { return is_bit_set(2); } + auto is_executable() const -> bool { return is_bit_set(2); } - auto contains_duplicate_data() -> bool { return is_bit_set(4); } + auto contains_duplicate_data() const -> bool { return is_bit_set(4); } - auto contains_strings() -> bool { return is_bit_set(5); } + auto contains_strings() const -> bool { return is_bit_set(5); } - auto section_header_info_is_section_header_table_index() -> bool { return is_bit_set(6); } + auto section_header_info_is_section_header_table_index() const -> bool { return is_bit_set(6); } - auto preserve_ordering_after_combination() -> bool { return is_bit_set(7); } + auto preserve_ordering_after_combination() const -> bool { return is_bit_set(7); } - auto requires_special_os_processing() -> bool { return is_bit_set(8); } + auto requires_special_os_processing() const -> bool { return is_bit_set(8); } - auto is_section_group_member() -> bool { return is_bit_set(9); } + auto is_section_group_member() const -> bool { return is_bit_set(9); } - auto holds_thread_local_data() -> bool { return is_bit_set(10); } + auto holds_thread_local_data() const -> bool { return is_bit_set(10); } - auto is_compressed() -> bool { return is_bit_set(11); } + auto is_compressed() const -> bool { return is_bit_set(11); } - auto has_special_ordering_requirements() -> bool { return is_bit_set(30); } + auto has_special_ordering_requirements() const -> bool { return is_bit_set(30); } - auto is_excluded_unless_referenced_or_allocated() -> bool { return is_bit_set(31); } + auto is_excluded_unless_referenced_or_allocated() const -> bool { return is_bit_set(31); } + + auto operator==(elf_section_flags const & other) const -> bool { return flags == other.flags; } private: - auto is_bit_set(uint8_t index) -> bool { return flags[index] == 1; } + auto is_bit_set(uint8_t index) const -> bool { return flags[index] == 1; } std::bitset<64U> flags; }; /** - * https://docs.oracle.com/cd/E19455-01/806-3773/elf-2/index.html + * @brief Defines the data included in a section header, where each section has exactly one section header. + * See https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html for more information */ struct elf_section_header { @@ -171,6 +174,19 @@ namespace teachos::arch::memory uint32_t additional_information; uint64_t address_alignment; uint64_t fixed_table_entry_size; + + /** + * @brief Detect whether e section header is inactive or not, should always be the case for the first entry in the + * sections table + * @return Whether the current section header is actually null or not, requires all fields besides section_size and + * other_section to actually contain 0 + */ + auto is_null() const -> bool + { + return name_table_index == 0U && type == elf_section_type::UNSPECIFIED && flags == 0U && virtual_address == 0U && + file_offset == 0U && additional_information == 0U && address_alignment == 0U && + fixed_table_entry_size == 0U; + } }; /** -- cgit v1.2.3 From 8773024d1b4e756fe5d3494479247c64c7ad8491 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 8 Oct 2024 09:51:26 +0000 Subject: begin implementing frame allocator --- .../x86_64/include/arch/memory/frame_allocator.hpp | 72 +++++++++++++++++----- 1 file changed, 57 insertions(+), 15 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/frame_allocator.hpp b/arch/x86_64/include/arch/memory/frame_allocator.hpp index 8dee848..35d7360 100644 --- a/arch/x86_64/include/arch/memory/frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/frame_allocator.hpp @@ -1,6 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_FRAME_HPP #define TEACHOS_ARCH_X86_64_MEMORY_FRAME_HPP +#include "multiboot.hpp" #include #include @@ -8,20 +9,26 @@ namespace teachos::arch::memory { namespace { - const size_t PAGE_FRAME_SIZE = 4096U; + const std::size_t PAGE_FRAME_SIZE = 4096U; } struct frame { - size_t frame_number; + std::size_t frame_number; - frame(size_t frame_number) + frame(std::size_t frame_number) : frame_number(frame_number) { // Nothing to do } - auto containing_address(size_t address) -> frame { return frame{address / PAGE_FRAME_SIZE}; } + static auto containing_address(std::size_t address) -> frame { return frame{address / PAGE_FRAME_SIZE}; } + + constexpr bool operator==(const frame & other) const noexcept { return frame_number == other.frame_number; } + constexpr bool operator>(const frame & other) const noexcept { return frame_number > other.frame_number; } + constexpr bool operator<(const frame & other) const noexcept { return frame_number < other.frame_number; } + constexpr bool operator>=(const frame & other) const noexcept { return frame_number >= other.frame_number; } + constexpr bool operator<=(const frame & other) const noexcept { return frame_number <= other.frame_number; } }; struct frame_allocator @@ -30,18 +37,53 @@ namespace teachos::arch::memory virtual auto deallocate_frame(frame frame) -> void = 0; }; - struct area_frame_allocator : public frame_allocator + // TODO: FIX CONCEPT USAGE + // template + // concept FrameAllocator = requires(T t) { + // { t.allocate_frame() } -> std::optional; + // { t.deallocate_frame() } -> void; + // }; + + // template + struct area_frame_allocator : frame_allocator { - frame next_free_frame; - // std::optional current_area; - // memory_area * areas; - frame kernel_start; - frame kernel_end; - frame multiboot_start; - frame multiboot_end; - - auto allocate_frame() -> std::optional override; - auto deallocate_frame(frame frame) -> void override; + frame next_free_frame{0}; //!< The frame after the last allocated one + std::optional current_area{std::nullopt}; //!< The current memory area + arch::memory::memory_area * areas; //!< A list of all memory areas + frame kernel_start; //!< The start address of the kernel code in memory + frame kernel_end; //!< The end address of the kernel code in memory + frame multiboot_start; //!< The start address of the multiboot code in memory + frame multiboot_end; //!< The end address of the multiboot code in memory + + area_frame_allocator(std::size_t kernel_start, std::size_t kernel_end, std::size_t multiboot_start, + std::size_t multiboot_end, arch::memory::memory_area * memory_areas) + : kernel_start(frame{kernel_start}) + , kernel_end(frame{kernel_end}) + , multiboot_start(frame{multiboot_start}) + , multiboot_end(frame{multiboot_end}) + , areas(memory_areas) + { + choose_next_area(); + } + + /** + * @brief Allocate memory be finding and returning a free frame + * + * The frame allocation executes multiple checks before returning + * the 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 + */ + auto allocate_frame() -> std::optional; + auto deallocate_frame(frame frame) -> void; + + private: + /** + * @brief Find the next memory area and write it into current_area + */ + auto choose_next_area() -> void; }; } // namespace teachos::arch::memory -- cgit v1.2.3 From 7edd03e9a14a3025b4d2b2ff51d838d20b79b2c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 8 Oct 2024 11:30:01 +0000 Subject: Added doxygen comments to all fields and structs --- arch/x86_64/include/arch/io/port_io.hpp | 1 - .../x86_64/include/arch/memory/frame_allocator.hpp | 86 +++-- arch/x86_64/include/arch/memory/multiboot.hpp | 345 ++++++++++++++------- 3 files changed, 287 insertions(+), 145 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/io/port_io.hpp b/arch/x86_64/include/arch/io/port_io.hpp index c0f1ef3..1945261 100644 --- a/arch/x86_64/include/arch/io/port_io.hpp +++ b/arch/x86_64/include/arch/io/port_io.hpp @@ -8,7 +8,6 @@ namespace teachos::arch::io { - /** * @brief An I/O port of a given size at a given address. * diff --git a/arch/x86_64/include/arch/memory/frame_allocator.hpp b/arch/x86_64/include/arch/memory/frame_allocator.hpp index 35d7360..3989cdf 100644 --- a/arch/x86_64/include/arch/memory/frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/frame_allocator.hpp @@ -4,6 +4,7 @@ #include "multiboot.hpp" #include #include +#include namespace teachos::arch::memory { @@ -12,51 +13,74 @@ namespace teachos::arch::memory const std::size_t PAGE_FRAME_SIZE = 4096U; } + /** + * @brief Specific frame containing helper functions to determine if a specific address is in that frame or not + */ struct frame { - std::size_t frame_number; + std::size_t frame_number; ///< Index number of the current frame, used to distinguish it from other frames + /** + * @brief Constructor + * + * @param frame_number Index number that should be assigned to this frame + */ frame(std::size_t frame_number) : frame_number(frame_number) { // Nothing to do } + /** + * @brief Returns the 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 + */ static auto containing_address(std::size_t address) -> frame { return frame{address / PAGE_FRAME_SIZE}; } - constexpr bool operator==(const frame & other) const noexcept { return frame_number == other.frame_number; } - constexpr bool operator>(const frame & other) const noexcept { return frame_number > other.frame_number; } - constexpr bool operator<(const frame & other) const noexcept { return frame_number < other.frame_number; } - constexpr bool operator>=(const frame & other) const noexcept { return frame_number >= other.frame_number; } - constexpr bool operator<=(const frame & other) const noexcept { return frame_number <= other.frame_number; } - }; + /** + * @brief Defaulted equals operator + */ + constexpr auto operator==(const frame & other) const -> bool = default; - struct frame_allocator - { - virtual auto allocate_frame() -> std::optional = 0; - virtual auto deallocate_frame(frame frame) -> void = 0; + /** + * @brief Defaulted three-way comparsion operator + */ + constexpr auto operator<=>(const frame & other) const -> std::partial_ordering = default; }; - // TODO: FIX CONCEPT USAGE - // template - // concept FrameAllocator = requires(T t) { - // { t.allocate_frame() } -> std::optional; - // { t.deallocate_frame() } -> void; - // }; + template + concept FrameAllocator = requires(T t) { + { t.allocate_frame() } -> std::optional; + { t.deallocate_frame() } -> void; + }; - // template - struct area_frame_allocator : frame_allocator + /** + * @brief Allocates memory using memory areas read from the multiboot2 information pointer + * + */ + struct area_frame_allocator { - frame next_free_frame{0}; //!< The frame after the last allocated one - std::optional current_area{std::nullopt}; //!< The current memory area - arch::memory::memory_area * areas; //!< A list of all memory areas - frame kernel_start; //!< The start address of the kernel code in memory - frame kernel_end; //!< The end address of the kernel code in memory - frame multiboot_start; //!< The start address of the multiboot code in memory - frame multiboot_end; //!< The end address of the multiboot code in memory + frame next_free_frame{0}; //!< The frame after the last allocated one + std::optional current_area{std::nullopt}; //!< The current memory area + memory_area * areas; //!< Pointer to the first element of all memory areas + frame kernel_start; //!< The start address of the kernel code in memory + frame kernel_end; //!< The end address of the kernel code in memory + frame multiboot_start; //!< The start address of the multiboot code in memory + frame multiboot_end; //!< The end address of the multiboot code in memory + /** + * @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 + */ area_frame_allocator(std::size_t kernel_start, std::size_t kernel_end, std::size_t multiboot_start, - std::size_t multiboot_end, arch::memory::memory_area * memory_areas) + std::size_t multiboot_end, memory_area * memory_areas) : kernel_start(frame{kernel_start}) , kernel_end(frame{kernel_end}) , multiboot_start(frame{multiboot_start}) @@ -67,7 +91,7 @@ namespace teachos::arch::memory } /** - * @brief Allocate memory be finding and returning a free frame + * @brief Allocate memory by finding and returning a free frame * * The frame allocation executes multiple checks before returning * the frame that is available to allocate. It must at least @@ -77,6 +101,12 @@ namespace teachos::arch::memory * - update the next_free_frame after finding a free frame */ auto allocate_frame() -> std::optional; + + /** + * @brief Deallocates a previously allocated frame + * + * @param frame Previously allocated frame that should be allocated + */ auto deallocate_frame(frame frame) -> void; private: diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp index f6ff480..5990260 100644 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -6,154 +6,264 @@ namespace teachos::arch::memory { - /* - * Define all multiboot tag types to ther respective values - * The gnu boot information format is defined here: - * https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Boot-information-format + /** + * @brief Defines all possible types a multiboot2 tag structure can have. + * See + * https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Boot-information-format for more information. */ enum class multi_boot_tag_type : uint32_t { - END, - CMDLINE, - BOOT_LOADER_NAME, - MODULE, - BASIC_MEMORY_INFO, - BOOTDEV, - MEMORY_MAP, - VBE, - FRAMEBUFFER, - ELF_SECTIONS, - APM, - EFI32, - EFI64, - SMBIOS, - ACPI_OLD, - ACPI_NEW, - NETWORK, - EFI_MEMORY_MAP, - EFI_BS, - EFI32_IH, - EFI64_IH, - LOAD_BASE_ADDRESS + END, ///< Signals final tag for the multiboot2 information structure + CMDLINE, ///< Contains the command line string + BOOT_LOADER_NAME, ///< Contains the name of the boot loader booting the kernel + MODULE, ///< Indicates the boot module which was loaded along the kernel image + BASIC_MEMORY_INFO, ///< Contains the amount of lower (0MB start address) and upper memory (1MB start address) + BOOTDEV, ///< Indicates which BIOS disk device the hoot loader has loaded the OS image from + MEMORY_MAP, ///< Describes the memory layout of the system with individual areas and their flags + VBE_INFO, ///< Includes information to access and utilize the device GPU + FRAMEBUFFER, ///< VBE framebuffer information + ELF_SECTIONS, ///< Includes list of all section headers from the loaded ELF kernel + APM_INFO, ///< Advanced Power Management information + EFI32, ///< EFI 32 bit system table pointer + EFI64, ///< EFI 64 bit system table pointer + SMBIOS, ///< Contains copy of all Sytem Management BIOS tables + ACPI_OLD, ///< Contains copy of RSDP as defined per ACPI1.0 specification + ACPI_NEW, ///< Contains copy of RSDP as defined per ACPI2.0 or later specification + NETWORK, ///< Contains network information specified specified as DHCP + EFI_MEMORY_MAP, ///< Contains EFI memory map + EFI_BS_NOT_TERMINATED, ///< Indicated ExitBootServies wasn't called + EFI32_IMAGE_HANDLE, ///< EFI 32 bit image handle pointer + EFI64_IMAGE_HANDLE, ///< EFI 64 bit imae handle pointer + LOAD_BASE_ADDRESS ///< Contains image load base physical address }; + /** + * @brief Basic structure that every entry in the multi_boot_tag array of the multi_boot_info struct has to begin + * with. + */ struct multi_boot_tag { - multi_boot_tag_type type; - uint32_t size; + multi_boot_tag_type type; ///< Specific type of this multi_boot_tag entry, used to differentiate handling + uint32_t size; ///< Total size of this multi_boot_tag entry with all fields of the actual type }; + /** + * @brief Basic structure the multiboot_information_pointer points too and which contains all information of + * multiboot2 in the tags array of different types. + */ struct multi_boot_info { - uint32_t total_size; - /* - * field "tags" is an array of multi_boot_tag, however the array is never - * being accessed by index we don't know the real size at compile-time, - * and using an array definition with size 0 produces a compiler error. - */ - alignas(8) struct multi_boot_tag tags; + uint32_t total_size; ///< Total size of all multi_boot_tags and their data + alignas(8) struct multi_boot_tag tags; ///< Specific tags }; + /** + * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type + * multi_boot_tag_type::BASIC_MEMORY_INFO. + */ struct memory_info { - multi_boot_tag tag; - uint32_t mem_lower; - uint32_t mem_upper; + multi_boot_tag tag; ///< Basic multi_boot_tag information + uint32_t mem_lower; ///< Amount of lower memory (0MB start address) + uint32_t mem_upper; ///< Amount of upper memory (1MB start address) }; + /** + * @brief Defines all memory area types possible that the memory region can be in. + */ enum class memory_area_type : uint32_t { - AVAILABLE = 1, - RESERVED, - ACPI_AVAILABLE, - RESERVED_HIBERNATION, - DEFECTIVE + AVAILABLE = 1, ///< Region is available for use by the OS + RESERVED, ///< Region is reserved by firmware or bootloader and should not be used by OS + ACPI_AVAILABLE, ///< Region is reclaimable by OS after ACPI event + RESERVED_HIBERNATION, ///< Region is used for Non-volatile Storage (NVS) + DEFECTIVE ///< Region is defective or unusable }; + /** + * @brief Defines an entry in the entries array of the memory_map struct. + */ struct memory_area { - uint64_t base_address; - uint64_t area_length; - alignas(8) memory_area_type type; + uint64_t base_address; ///< Base address the memory region starts at + uint64_t area_length; ///< Size of the memory region, added to base_address results in the final address + alignas(8) memory_area_type type; ///< Specific type of memory the region can contain }; + /** + * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type + * multi_boot_tag_type::MEMORY_MAP. + */ struct memory_map { - multi_boot_tag tag; - uint32_t entry_size; - uint32_t entry_version; - /* - * field "entries" is an array of memory_area, however the array is never - * being accessed by index, we don't know the real size at compile-time, - * and using an array definition with size 0 produces a compiler error. - */ - struct memory_area entries; + multi_boot_tag tag; ///< Basic multi_boot_tag information + uint32_t entry_size; ///< Size of each entry in the memory_area array. Guaranteed multiple of 8 + uint32_t entry_version; ///< Version of the entries, currently 0 + struct memory_area entries; ///< Specific memory regions }; /** - * https://refspecs.linuxfoundation.org/LSB_2.1.0/LSB-Core-generic/LSB-Core-generic/elftypes.html + * @brief Defines all elf section types an elf section header can have. + * The first section will always be INACTIVE, there can only ever be one DYNAMIC section and only either one + * DYNAMIC_SYMBOL_TABLE or SYMBOL_TABLE. See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html + * for more information. */ enum class elf_section_type : uint32_t { - INACTIVE, - PROGRAMM, - SYMBOL_TABLE, - STRING_TABLE, - RELOCATION_ENTRY_WITH_EXPLICIT_ADDENDS, - SYMBOL_HASH_TABLE, - DYNAMIC, - NOTE, - EMPTY, - RELOCATION_ENTRY_WITHOUT_EXPLICIT_ADDENDS, - UNSPECIFIED, - DYNAMIC_SYMBOL, - INITALIZATION_FUNCTION_ARRAY = 14, - TERMINATION_FUNCTION_ARRAY, - PRE_INITALIZATION_FUNCTION_ARRAY + INACTIVE, ///< (SHT_NULL) Unused, meaning all values are zeroed out + PROGRAMM, ///< (SHT_PROGBITS) Program data + SYMBOL_TABLE, ///< (SHT_SYMBTAB) Contains actual entries pointed to in symbol hash table + STRING_TABLE, ///< (SHT_STRTAB) Contains symbols, section and deubbging null-terminated strings + RELOCATION_ENTRY_WITH_ADDENDS, ///< (SHT_RELA) Only used on 64 bit systems + SYMBOL_HASH_TABLE, ///< (SHT_HASH) Hash table used by dynamic linker to locate symbols + DYNAMIC, ///< (SHT_DYNAMIC) Contains dynamic linking information + NOTE, ///< (SHT_NOTE) Stores information that marks files in some way + EMPTY, ///< (SHT_NOBITS) Program data section, that occupies no space in the file (.bss) + RELOCATION_ENTRY_WITHOUT_ADDENDS, ///< (SHT_REL) Only used on 32 bit systems + UNSPECIFIED, ///< (SHT_SHLIB) Reserved but has unspecified semantics + DYNAMIC_SYMBOL_TABLE, ///< (SHT_DYNSYM) Holds minimal set of symbols adequate for dynamic linking + INITALIZATION_FUNCTION_ARRAY = 14, ///< (SHT_INIT_ARRAY) Array of pointers to intialization functions () -> void + TERMINATION_FUNCTION_ARRAY, ///< (SHT_FINI_ARRAY) Array of pointers to termination functions () -> void + PRE_INITALIZATION_FUNCTION_ARRAY ///< (SHT_PRE_INIT_ARRAY) Array of pointers to functions invoked before other + ///< initalization functions () -> void }; /** - * https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html + * @brief Defines helper function for all states that the elf section flags of an elf section header can + * have. See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html + * See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information. */ - class elf_section_flags + struct elf_section_flags { - public: - elf_section_flags(uint64_t flags) + /** + * @brief Constructor. + * + * @param flags Actual value read from the elf section header, which should be converted into a std::bitset, to + * allow reading the state of single bits more easily. + */ + explicit elf_section_flags(uint64_t flags) : flags(flags) { // Nothing to do } - auto writeable() const -> bool { return is_bit_set(0); } + /** + * @brief (SHF_WRITE) Wether the current section is writable or not. Read from bit index 0. + * + * @return Current section is writable. + */ + auto writeable() const -> bool; - auto occupies_memory() const -> bool { return is_bit_set(1); } + /** + * @brief (SHF_ALLOC) Whether the current section occupies memory during execution or not. Read from bit index 1. + * + * @return Current section occupies memory during execution. + */ + auto occupies_memory() const -> bool; - auto is_executable() const -> bool { return is_bit_set(2); } + /** + * @brief (SHF_EXECINSTR) Whether the current section is executable or not. Read from bit index 2. + * + * @return Current section is executable. + */ + auto is_executable() const -> bool; - auto contains_duplicate_data() const -> bool { return is_bit_set(4); } + /** + * @brief (SHF_MERGE) Whether the current section might be merged with another section or not. Read from bit + * index 4. + * + * @return Current section might be merged with another section + */ + auto contains_duplicate_data() const -> bool; - auto contains_strings() const -> bool { return is_bit_set(5); } + /** + * @brief (SHF_STRINGS) Whether the current section contains null-terminated strings or not. Read from bit + * index 5. + * + * @return Current section contains null-terminated strings + */ + auto contains_strings() const -> bool; - auto section_header_info_is_section_header_table_index() const -> bool { return is_bit_set(6); } + /** + * @brief (SHF_INFO_LINK) Whether the current section contains the section header table index in the (sh_info) + * additional_information variable or not. Read from bit index 6. + * + * @return Current section contains the section header table index in the (sh_info) + * additional_information variable + */ + auto section_header_info_is_section_header_table_index() const -> bool; - auto preserve_ordering_after_combination() const -> bool { return is_bit_set(7); } + /** + * @brief (SHF_LINK_ORDER) Whether the current section preserves order after combining with another section or not. + * Read from bit index 7. + * + * @return Current section preserves order after combining with another section + */ + auto preserve_ordering_after_combination() const -> bool; - auto requires_special_os_processing() const -> bool { return is_bit_set(8); } + /** + * @brief (SHF_OS_NONCONFORMING) Whether the current section requires non-standard OS specific handling of its code + * or data, which does not confirm to standard ELF specifications. Read from bit index 8. + * + * @return Current section requires non-standard OS specific handling + */ + auto requires_special_os_processing() const -> bool; - auto is_section_group_member() const -> bool { return is_bit_set(9); } + /** + * @brief (SHF_GROUP) Whether the current section is a member of a section group or not. Read from bit index 9. + * + * @return Current section is a member of a section group + */ + auto is_section_group_member() const -> bool; - auto holds_thread_local_data() const -> bool { return is_bit_set(10); } + /** + * @brief (SHF_TLS) Whether the current section holds thread-local data or not. Read from bit + * index 10. + * + * @return Current section holds thread-local data + */ + auto holds_thread_local_data() const -> bool; - auto is_compressed() const -> bool { return is_bit_set(11); } + /** + * @brief (SHF_COMPRESSED) Whether the current section contains compressed data or not. Read from bit + * index 11. + * + * @return Current section contains compressed data + */ + auto is_compressed() const -> bool; - auto has_special_ordering_requirements() const -> bool { return is_bit_set(30); } + /** + * @brief (SHF_ORDERED) Whether the current section has special ordering requirements, meaning it should be ordered + * in relation to other sections of the same type. Read from bit index 30. + * + * @return current section has special ordering requirements + */ + auto has_special_ordering_requirements() const -> bool; - auto is_excluded_unless_referenced_or_allocated() const -> bool { return is_bit_set(31); } + /** + * @brief (SHF_EXCLUDE) Whether the current section is excluded unless refereenced or allocated, used for LTO + * (Link-Time Optimizations). Read from bit index 31. + * + * @return Current section is excluded unless refereenced or allocated + */ + auto is_excluded_unless_referenced_or_allocated() const -> bool; - auto operator==(elf_section_flags const & other) const -> bool { return flags == other.flags; } + /** + * @brief Allows to compare the underlying std::bitset of two instances + * + * @param other Other instance that we want to compare with + * @return Whether the underlying std::bitset of both types is the same + */ + auto operator==(elf_section_flags const & other) const -> bool; private: - auto is_bit_set(uint8_t index) const -> bool { return flags[index] == 1; } + /** + * @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; }; @@ -164,41 +274,44 @@ namespace teachos::arch::memory */ struct elf_section_header { - uint32_t name_table_index; - elf_section_type type; - elf_section_flags flags; - uint64_t virtual_address; - uint64_t file_offset; - uint64_t section_size; - uint32_t other_section; - uint32_t additional_information; - uint64_t address_alignment; - uint64_t fixed_table_entry_size; - - /** - * @brief Detect whether e section header is inactive or not, should always be the case for the first entry in the + uint32_t name_table_index; ///< Index into the section header string table, specifies the name of the section + elf_section_type type; ///< Categorizes the sections content and semantics + elf_section_flags flags; ///< 1-bit flgas that describe section attributes + uint64_t virtual_address; ///< If section appears in memory image of a process, gives address at which the sections + ///< first byte should reside, otherwise 0 + uint64_t file_offset; ///< Offset from the beginning of the file to the first byte in the section. SHT_NOBITS + ///< contains the conceptual placement instead (because it occupies no space in the file) + uint64_t section_size; ///< Complete section size in bytes, SHT_NOBITS may have non-zero value but will always + ///< occupy no space in the file + uint32_t other_section; ///< Section header table index link, behaviour varies on type + ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link + uint32_t additional_information; ///< Extra information, behaviour varies on type + ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link + uint64_t address_alignment; ///< Possible address alignment constraints. Value of virutal_address must be 0 % value + ///< of address_alignment. Value 0 or 1 mean no alignment constraints + uint64_t fixed_table_entry_size; ///< If sections holds table with fixed-sized entries, this gives the size in + ///< bytes of each entry + + /** + * @brief Detect whether a section header is inactive or not, should always be the case for the first entry in the * sections table * @return Whether the current section header is actually null or not, requires all fields besides section_size and - * other_section to actually contain 0 + * other_section to contain 0 */ - auto is_null() const -> bool - { - return name_table_index == 0U && type == elf_section_type::UNSPECIFIED && flags == 0U && virtual_address == 0U && - file_offset == 0U && additional_information == 0U && address_alignment == 0U && - fixed_table_entry_size == 0U; - } + auto is_null() const -> bool; }; /** - * https://gist.github.com/x0nu11byt3/bcb35c3de461e5fb66173071a2379779 + * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type + * multi_boot_tag_type::ELF_SECTIONS. */ struct elf_symbols_section { - multi_boot_tag tag; - uint32_t number_of_sections; - uint32_t entry_size; - uint32_t section_index; - alignas(8) struct elf_section_header sections; + multi_boot_tag tag; ///< Basic multi_boot_tag information + uint32_t number_of_sections; ///< Number of sections in the sections array + uint32_t entry_size; ///< Size of each entry in the sections array + uint32_t section_index; ///< Index to the string table used for symbol names + alignas(8) struct elf_section_header sections; ///< Specific sectons }; } // namespace teachos::arch::memory -- cgit v1.2.3 From 88818847446c010ccbfce0690a20a4e6531ca6fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 8 Oct 2024 11:39:32 +0000 Subject: Add additional sanity checks to elf parsing --- arch/x86_64/include/arch/memory/multiboot.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp index 5990260..c049a29 100644 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -103,10 +103,8 @@ namespace teachos::arch::memory }; /** - * @brief Defines all elf section types an elf section header can have. - * The first section will always be INACTIVE, there can only ever be one DYNAMIC section and only either one - * DYNAMIC_SYMBOL_TABLE or SYMBOL_TABLE. See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html - * for more information. + * @brief Defines all elf section types an elf section header can have. See + * https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information. */ enum class elf_section_type : uint32_t { @@ -304,6 +302,8 @@ namespace teachos::arch::memory /** * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type * multi_boot_tag_type::ELF_SECTIONS. + * The first section in the sections array will always be INACTIVE, there can only ever be one DYNAMIC section and + * only either one DYNAMIC_SYMBOL_TABLE or SYMBOL_TABLE. */ struct elf_symbols_section { -- cgit v1.2.3 From 553f3a824511bb8107982b2b2737f5b1dff59855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 13 Oct 2024 08:28:30 +0000 Subject: Add missing cpp files to cmake and fix elf alignment issues --- arch/x86_64/include/arch/memory/frame_allocator.hpp | 8 ++++---- arch/x86_64/include/arch/memory/multiboot.hpp | 11 ++++++----- arch/x86_64/include/arch/video/vga/text.hpp | 1 - 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/frame_allocator.hpp b/arch/x86_64/include/arch/memory/frame_allocator.hpp index 3989cdf..a52cc46 100644 --- a/arch/x86_64/include/arch/memory/frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/frame_allocator.hpp @@ -52,8 +52,8 @@ namespace teachos::arch::memory template concept FrameAllocator = requires(T t) { - { t.allocate_frame() } -> std::optional; - { t.deallocate_frame() } -> void; + { t.allocate_frame() } -> std::same_as>; + { t.deallocate_frame() } -> std::same_as; }; /** @@ -81,11 +81,11 @@ namespace teachos::arch::memory */ 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) - : kernel_start(frame{kernel_start}) + : areas(memory_areas) + , kernel_start(frame{kernel_start}) , kernel_end(frame{kernel_end}) , multiboot_start(frame{multiboot_start}) , multiboot_end(frame{multiboot_end}) - , areas(memory_areas) { choose_next_area(); } diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp index c049a29..d66ca35 100644 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -307,11 +307,12 @@ namespace teachos::arch::memory */ struct elf_symbols_section { - multi_boot_tag tag; ///< Basic multi_boot_tag information - uint32_t number_of_sections; ///< Number of sections in the sections array - uint32_t entry_size; ///< Size of each entry in the sections array - uint32_t section_index; ///< Index to the string table used for symbol names - alignas(8) struct elf_section_header sections; ///< Specific sectons + multi_boot_tag tag; ///< Basic multi_boot_tag information + uint32_t number_of_sections; ///< Number of sections in the sections array + uint32_t entry_size; ///< Size of each entry in the sections array + uint32_t section_index; ///< Index to the string table used for symbol names + std::byte end; ///< Marks the end of the tag, used to mark the beginning of any additional data + ///< contained in the section, to ensure byte alignment is actually 4 byte }; } // namespace teachos::arch::memory diff --git a/arch/x86_64/include/arch/video/vga/text.hpp b/arch/x86_64/include/arch/video/vga/text.hpp index 9c4c701..79ec7be 100644 --- a/arch/x86_64/include/arch/video/vga/text.hpp +++ b/arch/x86_64/include/arch/video/vga/text.hpp @@ -121,7 +121,6 @@ namespace teachos::arch::video::vga::text */ auto write_char(char code_point, attribute attribute) -> void; - // TODO: Move concepts to their own file/folder template concept Integral = std::is_integral_v; -- cgit v1.2.3 From b3c8a1819226b7dbaad82623c8294b99c91297ef Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 13 Oct 2024 10:58:34 +0000 Subject: continue implementing frame allocator --- .../x86_64/include/arch/memory/frame_allocator.hpp | 45 +++++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/frame_allocator.hpp b/arch/x86_64/include/arch/memory/frame_allocator.hpp index a52cc46..fa22ce5 100644 --- a/arch/x86_64/include/arch/memory/frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/frame_allocator.hpp @@ -56,9 +56,41 @@ namespace teachos::arch::memory { t.deallocate_frame() } -> std::same_as; }; + /** + * @brief Iterator for memory areas + */ + class memory_area_iterator + { + memory_area * ptr; + + public: + std::size_t begin; + std::size_t end; + + explicit memory_area_iterator(memory_area * p) + : ptr(p) + { + } + + memory_area & operator*() const { return *ptr; } + memory_area_iterator & operator++() + { + ++ptr; + return *this; + } + + memory_area_iterator operator++(int) + { + memory_area_iterator temp = *this; + ++(*this); + return temp; + } + + bool operator==(const memory_area_iterator & other) const { return ptr == other.ptr; } + }; + /** * @brief Allocates memory using memory areas read from the multiboot2 information pointer - * */ struct area_frame_allocator { @@ -70,6 +102,10 @@ namespace teachos::arch::memory frame multiboot_start; //!< The start address of the multiboot code in memory frame multiboot_end; //!< The end address of the multiboot code in memory + private: + uint8_t N; + + public: /** * @brief Constructor * @@ -80,12 +116,13 @@ namespace teachos::arch::memory * @param memory_areas Pointer to the first element of all memory areas */ 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) + std::size_t multiboot_end, memory_area * memory_areas, uint8_t area_count) : areas(memory_areas) , kernel_start(frame{kernel_start}) , kernel_end(frame{kernel_end}) , multiboot_start(frame{multiboot_start}) , multiboot_end(frame{multiboot_end}) + , N(area_count) { choose_next_area(); } @@ -109,6 +146,10 @@ namespace teachos::arch::memory */ auto deallocate_frame(frame frame) -> void; + memory_area_iterator begin() { return memory_area_iterator(areas); } + + memory_area_iterator end() { return memory_area_iterator(areas + N); } + private: /** * @brief Find the next memory area and write it into current_area -- cgit v1.2.3 From 8beb8b758c33cf1ac5357b31296927e7df8cf971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 14 Oct 2024 08:15:16 +0000 Subject: Fix typos, implementation in header and missing doxygen --- .../x86_64/include/arch/memory/frame_allocator.hpp | 122 ++++++++++++--------- 1 file changed, 70 insertions(+), 52 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/frame_allocator.hpp b/arch/x86_64/include/arch/memory/frame_allocator.hpp index fa22ce5..1fd1f08 100644 --- a/arch/x86_64/include/arch/memory/frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/frame_allocator.hpp @@ -10,7 +10,7 @@ namespace teachos::arch::memory { namespace { - const std::size_t PAGE_FRAME_SIZE = 4096U; + constexpr std::size_t PAGE_FRAME_SIZE = 4096U; ///< Default page size of x86_84 is always 4KiB } /** @@ -18,18 +18,12 @@ namespace teachos::arch::memory */ struct frame { - std::size_t frame_number; ///< Index number of the current frame, used to distinguish it from other frames - /** * @brief Constructor * * @param frame_number Index number that should be assigned to this frame */ - frame(std::size_t frame_number) - : frame_number(frame_number) - { - // Nothing to do - } + frame(std::size_t frame_number); /** * @brief Returns the frame the given address is contained in @@ -37,7 +31,7 @@ namespace teachos::arch::memory * @param address Address we want to get the corresponding frame for * @return Frame the given address is contained in */ - static auto containing_address(std::size_t address) -> frame { return frame{address / PAGE_FRAME_SIZE}; } + static auto containing_address(std::size_t address) -> frame; /** * @brief Defaulted equals operator @@ -48,6 +42,8 @@ namespace teachos::arch::memory * @brief Defaulted three-way comparsion operator */ constexpr auto operator<=>(const 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 }; template @@ -57,36 +53,48 @@ namespace teachos::arch::memory }; /** - * @brief Iterator for memory areas + * @brief Iterator for memory areas. */ - class memory_area_iterator + struct memory_area_iterator { - memory_area * ptr; + /** + * @brief Constructor + * + * @param p Underlying address the iterator should point too, ensure to not pass an invalid pointer + */ + explicit memory_area_iterator(memory_area * p); - public: - std::size_t begin; - std::size_t end; + /** + * @brief Dereferences the initally given pointer to its value. + * + * @return Reference to the value + */ + memory_area & operator*() const; - explicit memory_area_iterator(memory_area * p) - : ptr(p) - { - } + /** + * @brief Post increment operator. Returns a copy of the value + * + * @return Copy of the incremented underlying address + */ + memory_area_iterator operator++(int); - memory_area & operator*() const { return *ptr; } - memory_area_iterator & operator++() - { - ++ptr; - return *this; - } + /** + * @brief Pre increment operator. Returns a reference to the changed value + * + * @return Reference to the incremented underlying address + */ + memory_area_iterator & operator++(); - memory_area_iterator operator++(int) - { - memory_area_iterator temp = *this; - ++(*this); - return temp; - } + /** + * @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 + */ + bool operator==(memory_area_iterator const & other) const = default; - bool operator==(const memory_area_iterator & other) const { return ptr == other.ptr; } + private: + memory_area * ptr; ///< Underlying address the iterator is currently pointing too }; /** @@ -94,18 +102,6 @@ namespace teachos::arch::memory */ struct area_frame_allocator { - frame next_free_frame{0}; //!< The frame after the last allocated one - std::optional current_area{std::nullopt}; //!< The current memory area - memory_area * areas; //!< Pointer to the first element of all memory areas - frame kernel_start; //!< The start address of the kernel code in memory - frame kernel_end; //!< The end address of the kernel code in memory - frame multiboot_start; //!< The start address of the multiboot code in memory - frame multiboot_end; //!< The end address of the multiboot code in memory - - private: - uint8_t N; - - public: /** * @brief Constructor * @@ -114,15 +110,16 @@ namespace teachos::arch::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) - : areas(memory_areas) - , kernel_start(frame{kernel_start}) - , kernel_end(frame{kernel_end}) - , multiboot_start(frame{multiboot_start}) - , multiboot_end(frame{multiboot_end}) - , N(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)) { choose_next_area(); } @@ -146,15 +143,36 @@ namespace teachos::arch::memory */ auto deallocate_frame(frame frame) -> void; - memory_area_iterator begin() { return memory_area_iterator(areas); } + /** + * @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 + * + * @return Iterator pointing to first element of the memory area + */ + auto begin() -> memory_area_iterator; - memory_area_iterator end() { return memory_area_iterator(areas + N); } + /** + * @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 + * + * @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 */ auto choose_next_area() -> void; + + frame next_free_frame{0}; ///< The frame after the last allocated one + std::optional 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 }; } // namespace teachos::arch::memory -- cgit v1.2.3 From 7fc99d55ffff20b49dc4088efc95b68b3d33a45b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 14 Oct 2024 09:47:49 +0000 Subject: Use scoped switch statements to extract calculations to variables --- arch/x86_64/include/arch/memory/multiboot.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp index d66ca35..3aee7fc 100644 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -49,7 +49,7 @@ namespace teachos::arch::memory /** * @brief Basic structure the multiboot_information_pointer points too and which contains all information of - * multiboot2 in the tags array of different types. + * multiboot2 in the tags array of different types. The start as well as the content has to be 8 byte aligned. */ struct multi_boot_info { @@ -109,7 +109,7 @@ namespace teachos::arch::memory enum class elf_section_type : uint32_t { INACTIVE, ///< (SHT_NULL) Unused, meaning all values are zeroed out - PROGRAMM, ///< (SHT_PROGBITS) Program data + PROGRAMM, ///< (SHT_PROGBITS) Program data (DATA, CODE) SYMBOL_TABLE, ///< (SHT_SYMBTAB) Contains actual entries pointed to in symbol hash table STRING_TABLE, ///< (SHT_STRTAB) Contains symbols, section and deubbging null-terminated strings RELOCATION_ENTRY_WITH_ADDENDS, ///< (SHT_RELA) Only used on 64 bit systems @@ -146,7 +146,9 @@ namespace teachos::arch::memory } /** - * @brief (SHF_WRITE) Wether the current section is writable or not. Read from bit index 0. + * @brief (SHF_WRITE) Wether the current section is writable at runtime or not. If it isn't then the section is + * assumed to be READONLY and only that behaviour is shown in the objdump -h of the kernel file. Read from bit index + * 0. * * @return Current section is writable. */ -- cgit v1.2.3 From 563a3dcbc1f2d26adcd6761358c45d635738f3c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 14 Oct 2024 12:42:54 +0000 Subject: Add more info on which elf flag means which objdump flag --- arch/x86_64/include/arch/memory/multiboot.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp index 3aee7fc..35b483e 100644 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -147,7 +147,7 @@ namespace teachos::arch::memory /** * @brief (SHF_WRITE) Wether the current section is writable at runtime or not. If it isn't then the section is - * assumed to be READONLY and only that behaviour is shown in the objdump -h of the kernel file. Read from bit index + * assumed to be READONLY and only that flag is shown in the objdump -h of the kernel file. Read from bit index * 0. * * @return Current section is writable. @@ -155,14 +155,16 @@ namespace teachos::arch::memory auto writeable() const -> bool; /** - * @brief (SHF_ALLOC) Whether the current section occupies memory during execution or not. Read from bit index 1. + * @brief (SHF_ALLOC) Whether the current section occupies memory during execution or not. ALLOC flag is shown in + * the objdump -h of the kernel file. Read from bit index 1. * * @return Current section occupies memory during execution. */ auto occupies_memory() const -> bool; /** - * @brief (SHF_EXECINSTR) Whether the current section is executable or not. Read from bit index 2. + * @brief (SHF_EXECINSTR) Whether the current section is executable or not. CODE flag is shown in the object dump. + * Read from bit index 2. * * @return Current section is executable. */ -- cgit v1.2.3 From 38e0b13ab9a4997fdf9f311fd125825919d2e6c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 14 Oct 2024 14:03:27 +0000 Subject: Start developing paging --- .../x86_64/include/arch/memory/frame_allocator.hpp | 117 ++++++++-------- arch/x86_64/include/arch/memory/multiboot.hpp | 2 +- arch/x86_64/include/arch/memory/paging.hpp | 150 +++++++++++++++++++++ arch/x86_64/include/arch/video/vga/io.hpp | 8 +- arch/x86_64/include/arch/video/vga/text.hpp | 32 ++--- 5 files changed, 229 insertions(+), 80 deletions(-) create mode 100644 arch/x86_64/include/arch/memory/paging.hpp (limited to 'arch/x86_64/include') 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 concept FrameAllocator = requires(T t) { - { t.allocate_frame() } -> std::same_as>; + { t.allocate_frame() } -> std::same_as>; { t.deallocate_frame() } -> std::same_as; }; @@ -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; + auto allocate_frame() -> std::optional; /** - * @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 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 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; + + 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."); -- cgit v1.2.3 From 205934ca45d591924b4be6e7ae5a8849958e0cf6 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 15 Oct 2024 08:23:39 +0000 Subject: continue implementing paging --- .../include/arch/exception_handling/assert.hpp | 11 +++ .../x86_64/include/arch/memory/frame_allocator.hpp | 7 ++ arch/x86_64/include/arch/memory/paging.hpp | 99 ++++++---------------- 3 files changed, 43 insertions(+), 74 deletions(-) create mode 100644 arch/x86_64/include/arch/exception_handling/assert.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/exception_handling/assert.hpp b/arch/x86_64/include/arch/exception_handling/assert.hpp new file mode 100644 index 0000000..eba43ac --- /dev/null +++ b/arch/x86_64/include/arch/exception_handling/assert.hpp @@ -0,0 +1,11 @@ +namespace teachos::arch::exception_handling +{ + /** + * @brief assert a condition to be true, if not do not continue + * execution of the code and print message to screen + * + * @param condition + * @param message + */ + auto assert(bool condition, char const * message) -> void; +} // namespace teachos::arch::exception_handling \ No newline at end of file diff --git a/arch/x86_64/include/arch/memory/frame_allocator.hpp b/arch/x86_64/include/arch/memory/frame_allocator.hpp index ab93231..69c108c 100644 --- a/arch/x86_64/include/arch/memory/frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/frame_allocator.hpp @@ -31,6 +31,13 @@ namespace teachos::arch::memory */ static auto containing_address(std::size_t address) -> physical_frame; + /** + * @brief TODO + * + * @return uint64_t + */ + auto start_address() const -> uint64_t; + /** * @brief Defaulted equals operator. */ diff --git a/arch/x86_64/include/arch/memory/paging.hpp b/arch/x86_64/include/arch/memory/paging.hpp index a5408e1..1870c28 100644 --- a/arch/x86_64/include/arch/memory/paging.hpp +++ b/arch/x86_64/include/arch/memory/paging.hpp @@ -42,72 +42,6 @@ namespace teachos::arch::memory */ 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. @@ -124,6 +58,22 @@ namespace teachos::arch::memory */ auto calculate_pointed_to_frame() const -> std::optional; + /** + * @brief TODO + * + * @param frame + */ + auto set(physical_frame frame) -> void; + + /** + * @brief TODO + * + * @param b + * @return true + * @return false + */ + auto contains_flags(std::bitset<64U> b) const -> bool; + private: /** * @brief Extracts the physical address from the underlying bitset read from bit index 12 - 51. Is a 52 bit page @@ -134,17 +84,18 @@ namespace teachos::arch::memory */ 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. }; + + /** + * @brief TODO + * + */ + struct page_table + { + entry entries[PAGE_TABLE_ENTRY_COUNT]; + }; } // namespace teachos::arch::memory #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_HPP -- cgit v1.2.3 From 03d3dec4807d6adcfc5e21bd13992014900b4eac Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 15 Oct 2024 08:40:56 +0000 Subject: implement page table members --- arch/x86_64/include/arch/memory/frame_allocator.hpp | 4 ++-- arch/x86_64/include/arch/memory/paging.hpp | 21 +++++++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/frame_allocator.hpp b/arch/x86_64/include/arch/memory/frame_allocator.hpp index 69c108c..3d1f826 100644 --- a/arch/x86_64/include/arch/memory/frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/frame_allocator.hpp @@ -32,9 +32,9 @@ namespace teachos::arch::memory static auto containing_address(std::size_t address) -> physical_frame; /** - * @brief TODO + * @brief Evaluates the start address of the physical frame * - * @return uint64_t + * @return start address of the physical frame */ auto start_address() const -> uint64_t; diff --git a/arch/x86_64/include/arch/memory/paging.hpp b/arch/x86_64/include/arch/memory/paging.hpp index 1870c28..43f13e0 100644 --- a/arch/x86_64/include/arch/memory/paging.hpp +++ b/arch/x86_64/include/arch/memory/paging.hpp @@ -89,11 +89,28 @@ namespace teachos::arch::memory }; /** - * @brief TODO - * + * @brief A Page table containing 512 entries */ struct page_table { + /** + * @brief Set every entry of the page to unused + */ + auto zero_entries() -> void; + + /** + * @brief Index operator overload to access specific entries directy + * + * @param index + * @return The address of the accessed entry + */ + entry & operator[](size_t index) + { + arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); + return entries[index]; + } + + private: entry entries[PAGE_TABLE_ENTRY_COUNT]; }; } // namespace teachos::arch::memory -- cgit v1.2.3 From 11f9c91e602bd0231e6bc402418dedf445e47402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 15 Oct 2024 08:45:29 +0000 Subject: Adding enum flags --- arch/x86_64/include/arch/memory/multiboot.hpp | 146 +++++++------------------- arch/x86_64/include/arch/memory/paging.hpp | 47 ++++++--- 2 files changed, 67 insertions(+), 126 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp index 93d214c..6fc10df 100644 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -133,6 +133,35 @@ namespace teachos::arch::memory */ struct elf_section_flags { + /** + * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + */ + enum bitset : uint32_t + { + WRITABLE = 1 << 0, ///< (SHF_WRITE) Section is writable at runtime. If it isn't then the section + ///< is assumed to be READONLY and only that flag is shown in the objdump. + OCCUPIES_MEMORY = 1 << 1, ///< (SHF_ALLOC) Section occupies memory during execution. + ///< ALLOC flag is shown in the objdump. + EXECUTABLE_CODE = 1 << 2, ///< (SHF_EXECINSTR) Section is executable. CODE flag is shown in the object dump. + DUPLICATE_DATA = 1 << 4, ///< (SHF_MERGE) Section might be merged with another section. + CONTAINS_STRING = 1 << 5, ///< (SHF_STRINGS) Section contains null-terminated strings. + SECTION_HEADER_INFO_IS_SECTION_HEADER_TABLE_INDEX = + 1 << 6, ///< (SHF_INFO_LINK) Section contains the section header table index in the (sh_info) + ///< additional_information variable. + PRESERVE_ORDERING_AFTER_COMBINATION = + 1 << 7, ///< (SHF_LINK_ORDER) Section preserves order after combining with another section. + REQUIRES_SPECIAL_OS_PROCESSING = + 1 << 8, ///< (SHF_OS_NONCONFORMING) Section requires non-standard OS specific handling of its code or + ///< data, which does not confirm to standard ELF specifications. + SECTION_GROUP_MEMBER = 1 << 9, ///< (SHF_GROUP) Section is a member of a section group. + HOLDS_THREAD_LOCAL_DATA = 1 << 10, ///< (SHF_TLS) Section holds thread-local data. + COMPRESSED = 1 << 11, ///< (SHF_COMPRESSED) Section contains compressed data. + SPECIAL_ORDERING_REQUIREMENTS = 1 << 30, ///< (SHF_ORDERED) Section has special ordering requirements, meaning it + ///< should be ordered in relation to other sections of the same type + EXCLUDED_UNLESS_REFERENCED_OR_ALLOCATED = 1 << 31, ///< (SHF_EXCLUDE)Section is excluded unless referenced or + ///< allocated, used for LTO (Link-Time Optimizations) + }; + /** * @brief Constructor. * @@ -146,109 +175,14 @@ namespace teachos::arch::memory } /** - * @brief (SHF_WRITE) Wether the current section is writable at runtime or not. If it isn't then the section is - * assumed to be READONLY and only that flag is shown in the objdump -h of the kernel file. Read from bit index - * 0. - * - * @return Current section is writable. - */ - auto writable() const -> bool; - - /** - * @brief (SHF_ALLOC) Whether the current section occupies memory during execution or not. ALLOC flag is shown in - * the objdump -h of the kernel file. Read from bit index 1. - * - * @return Current section occupies memory during execution. - */ - auto occupies_memory() const -> bool; - - /** - * @brief (SHF_EXECINSTR) Whether the current section is executable or not. CODE flag is shown in the object dump. - * Read from bit index 2. - * - * @return Current section is executable. - */ - auto is_executable() const -> bool; - - /** - * @brief (SHF_MERGE) Whether the current section might be merged with another section or not. Read from bit - * index 4. - * - * @return Current section might be merged with another section - */ - auto contains_duplicate_data() const -> bool; - - /** - * @brief (SHF_STRINGS) Whether the current section contains null-terminated strings or not. Read from bit - * index 5. - * - * @return Current section contains null-terminated strings - */ - auto contains_strings() const -> bool; - - /** - * @brief (SHF_INFO_LINK) Whether the current section contains the section header table index in the (sh_info) - * additional_information variable or not. Read from bit index 6. - * - * @return Current section contains the section header table index in the (sh_info) - * additional_information variable - */ - auto section_header_info_is_section_header_table_index() const -> bool; - - /** - * @brief (SHF_LINK_ORDER) Whether the current section preserves order after combining with another section or not. - * Read from bit index 7. + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset, meaning that all + * bits that are set in the given std::bitset also have to be set in the underlyng std::bitset. Any additional bits + * that are set are not relevant. * - * @return Current section preserves order after combining with another section + * @param flags Flags that we want to compare against and check if the underlying std::bitset has the same bits set. + * @return Whether the given flags are a subset or equivalent with the underlying std::bitset */ - auto preserve_ordering_after_combination() const -> bool; - - /** - * @brief (SHF_OS_NONCONFORMING) Whether the current section requires non-standard OS specific handling of its code - * or data, which does not confirm to standard ELF specifications. Read from bit index 8. - * - * @return Current section requires non-standard OS specific handling - */ - auto requires_special_os_processing() const -> bool; - - /** - * @brief (SHF_GROUP) Whether the current section is a member of a section group or not. Read from bit index 9. - * - * @return Current section is a member of a section group - */ - auto is_section_group_member() const -> bool; - - /** - * @brief (SHF_TLS) Whether the current section holds thread-local data or not. Read from bit - * index 10. - * - * @return Current section holds thread-local data - */ - auto holds_thread_local_data() const -> bool; - - /** - * @brief (SHF_COMPRESSED) Whether the current section contains compressed data or not. Read from bit - * index 11. - * - * @return Current section contains compressed data - */ - auto is_compressed() const -> bool; - - /** - * @brief (SHF_ORDERED) Whether the current section has special ordering requirements, meaning it should be ordered - * in relation to other sections of the same type. Read from bit index 30. - * - * @return current section has special ordering requirements - */ - auto has_special_ordering_requirements() const -> bool; - - /** - * @brief (SHF_EXCLUDE) Whether the current section is excluded unless refereenced or allocated, used for LTO - * (Link-Time Optimizations). Read from bit index 31. - * - * @return Current section is excluded unless refereenced or allocated - */ - auto is_excluded_unless_referenced_or_allocated() const -> bool; + auto contains_flags(std::bitset<64U> b) const -> bool; /** * @brief Allows to compare the underlying std::bitset of two instances @@ -256,17 +190,9 @@ namespace teachos::arch::memory * @param other Other instance that we want to compare with * @return Whether the underlying std::bitset of both types is the same */ - auto operator==(elf_section_flags const & other) const -> bool; + auto operator==(elf_section_flags const & other) const -> bool = default; private: - /** - * @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; }; diff --git a/arch/x86_64/include/arch/memory/paging.hpp b/arch/x86_64/include/arch/memory/paging.hpp index 43f13e0..aa20da7 100644 --- a/arch/x86_64/include/arch/memory/paging.hpp +++ b/arch/x86_64/include/arch/memory/paging.hpp @@ -30,6 +30,27 @@ namespace teachos::arch::memory */ struct entry { + /** + * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + */ + enum bitset : uint64_t + { + PRESENT = 1 << 0, ///< Page is in memory and therefore present. + ///< is assumed to be READONLY and only that flag is shown in the objdump. + WRITABLE = 1 << 1, ///< It is possible to write to the page. + USER_ACCESIBLE = 1 << 2, ///< Page can be accessed in user mode instead of only in kernel mode code. + WRITE_THROUGH_CACHING = 1 << 3, ///< Write to the page go directly to memory instead of the cache. + DISABLED_CACHING = 1 << 4, ///< Page uses caching. + ACCESSED = 1 << 5, ///< Page is currently in use. + DIRTY = 1 << 6, ///< Page has been writen too. + HUGE_PAGE = 1 << 7, ///< Page is huge (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. + GLOBAL = 1 << 8, ///< Page is not flushed from caches on address space switches (PGE bit of CR4 register + ///< has to be set) + EXECUTING_CODE_FORBIDDEN = + 1 << 63, ///< Page is forbidden from executing code (NXE bit in the EFER register has to be set) + }; + /** * @brief Whether the current page is unused, meaning the underlying std::bitset is 0. * @@ -42,14 +63,6 @@ namespace teachos::arch::memory */ auto set_unused() -> void; - /** - * @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. @@ -59,18 +72,20 @@ namespace teachos::arch::memory auto calculate_pointed_to_frame() const -> std::optional; /** - * @brief TODO + * @brief Copies the address from the given physical frame into the underlying std::bitset so future calls to + * calculate_physical_address() will return the new address instead of the old one. * - * @param frame + * @param frame Physical frame that contains the address we want to copy into our underlying std::bitset. */ - auto set(physical_frame frame) -> void; + auto set_address(physical_frame frame) -> void; /** - * @brief TODO + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset, meaning that all + * bits that are set in the given std::bitset also have to be set in the underlyng std::bitset. Any additional bits + * that are set are not relevant. * - * @param b - * @return true - * @return false + * @param flags Flags that we want to compare against and check if the underlying std::bitset has the same bits set. + * @return Whether the given flags are a subset or equivalent with the underlying std::bitset */ auto contains_flags(std::bitset<64U> b) const -> bool; @@ -85,7 +100,7 @@ namespace teachos::arch::memory auto calculate_physical_address() const -> std::size_t; 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. + ///< used for additional flags by the operating system. }; /** -- cgit v1.2.3 From 8524564b240d9859655603d1fb3717faf3cf558c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 15 Oct 2024 08:51:32 +0000 Subject: Fix problems with calculations inside enum (uses int32_t by default) --- arch/x86_64/include/arch/memory/multiboot.hpp | 39 ++++++++++++++------------- arch/x86_64/include/arch/memory/paging.hpp | 26 +++++++++--------- 2 files changed, 33 insertions(+), 32 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp index 6fc10df..c070e85 100644 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -138,28 +138,29 @@ namespace teachos::arch::memory */ enum bitset : uint32_t { - WRITABLE = 1 << 0, ///< (SHF_WRITE) Section is writable at runtime. If it isn't then the section - ///< is assumed to be READONLY and only that flag is shown in the objdump. - OCCUPIES_MEMORY = 1 << 1, ///< (SHF_ALLOC) Section occupies memory during execution. - ///< ALLOC flag is shown in the objdump. - EXECUTABLE_CODE = 1 << 2, ///< (SHF_EXECINSTR) Section is executable. CODE flag is shown in the object dump. - DUPLICATE_DATA = 1 << 4, ///< (SHF_MERGE) Section might be merged with another section. - CONTAINS_STRING = 1 << 5, ///< (SHF_STRINGS) Section contains null-terminated strings. + WRITABLE = 1U << 0U, ///< (SHF_WRITE) Section is writable at runtime. If it isn't then the section + ///< is assumed to be READONLY and only that flag is shown in the objdump. + OCCUPIES_MEMORY = 1U << 1U, ///< (SHF_ALLOC) Section occupies memory during execution. + ///< ALLOC flag is shown in the objdump. + EXECUTABLE_CODE = 1U << 2U, ///< (SHF_EXECINSTR) Section is executable. CODE flag is shown in the object dump. + DUPLICATE_DATA = 1U << 4U, ///< (SHF_MERGE) Section might be merged with another section. + CONTAINS_STRING = 1U << 5U, ///< (SHF_STRINGS) Section contains null-terminated strings. SECTION_HEADER_INFO_IS_SECTION_HEADER_TABLE_INDEX = - 1 << 6, ///< (SHF_INFO_LINK) Section contains the section header table index in the (sh_info) - ///< additional_information variable. + 1U << 6U, ///< (SHF_INFO_LINK) Section contains the section header table index in the (sh_info) + ///< additional_information variable. PRESERVE_ORDERING_AFTER_COMBINATION = - 1 << 7, ///< (SHF_LINK_ORDER) Section preserves order after combining with another section. + 1U << 7U, ///< (SHF_LINK_ORDER) Section preserves order after combining with another section. REQUIRES_SPECIAL_OS_PROCESSING = - 1 << 8, ///< (SHF_OS_NONCONFORMING) Section requires non-standard OS specific handling of its code or - ///< data, which does not confirm to standard ELF specifications. - SECTION_GROUP_MEMBER = 1 << 9, ///< (SHF_GROUP) Section is a member of a section group. - HOLDS_THREAD_LOCAL_DATA = 1 << 10, ///< (SHF_TLS) Section holds thread-local data. - COMPRESSED = 1 << 11, ///< (SHF_COMPRESSED) Section contains compressed data. - SPECIAL_ORDERING_REQUIREMENTS = 1 << 30, ///< (SHF_ORDERED) Section has special ordering requirements, meaning it - ///< should be ordered in relation to other sections of the same type - EXCLUDED_UNLESS_REFERENCED_OR_ALLOCATED = 1 << 31, ///< (SHF_EXCLUDE)Section is excluded unless referenced or - ///< allocated, used for LTO (Link-Time Optimizations) + 1U << 8U, ///< (SHF_OS_NONCONFORMING) Section requires non-standard OS specific handling of its code or + ///< data, which does not confirm to standard ELF specifications. + SECTION_GROUP_MEMBER = 1U << 9U, ///< (SHF_GROUP) Section is a member of a section group. + HOLDS_THREAD_LOCAL_DATA = 1U << 10U, ///< (SHF_TLS) Section holds thread-local data. + COMPRESSED = 1U << 11U, ///< (SHF_COMPRESSED) Section contains compressed data. + SPECIAL_ORDERING_REQUIREMENTS = + 1U << 30U, ///< (SHF_ORDERED) Section has special ordering requirements, meaning it + ///< should be ordered in relation to other sections of the same type + EXCLUDED_UNLESS_REFERENCED_OR_ALLOCATED = 1U << 31U, ///< (SHF_EXCLUDE)Section is excluded unless referenced or + ///< allocated, used for LTO (Link-Time Optimizations) }; /** diff --git a/arch/x86_64/include/arch/memory/paging.hpp b/arch/x86_64/include/arch/memory/paging.hpp index aa20da7..25246f6 100644 --- a/arch/x86_64/include/arch/memory/paging.hpp +++ b/arch/x86_64/include/arch/memory/paging.hpp @@ -35,20 +35,20 @@ namespace teachos::arch::memory */ enum bitset : uint64_t { - PRESENT = 1 << 0, ///< Page is in memory and therefore present. - ///< is assumed to be READONLY and only that flag is shown in the objdump. - WRITABLE = 1 << 1, ///< It is possible to write to the page. - USER_ACCESIBLE = 1 << 2, ///< Page can be accessed in user mode instead of only in kernel mode code. - WRITE_THROUGH_CACHING = 1 << 3, ///< Write to the page go directly to memory instead of the cache. - DISABLED_CACHING = 1 << 4, ///< Page uses caching. - ACCESSED = 1 << 5, ///< Page is currently in use. - DIRTY = 1 << 6, ///< Page has been writen too. - HUGE_PAGE = 1 << 7, ///< Page is huge (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. - GLOBAL = 1 << 8, ///< Page is not flushed from caches on address space switches (PGE bit of CR4 register - ///< has to be set) + PRESENT = 1UL << 0UL, ///< Page is in memory and therefore present. + ///< is assumed to be READONLY and only that flag is shown in the objdump. + WRITABLE = 1UL << 1UL, ///< It is possible to write to the page. + USER_ACCESIBLE = 1UL << 2UL, ///< Page can be accessed in user mode instead of only in kernel mode code. + WRITE_THROUGH_CACHING = 1UL << 3UL, ///< Write to the page go directly to memory instead of the cache. + DISABLED_CACHING = 1UL << 4UL, ///< Page uses caching. + ACCESSED = 1UL << 5UL, ///< Page is currently in use. + DIRTY = 1UL << 6UL, ///< Page has been writen too. + HUGE_PAGE = 1UL << 7UL, ///< Page is huge (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. + GLOBAL = 1UL << 8UL, ///< Page is not flushed from caches on address space switches (PGE bit of CR4 register + ///< has to be set) EXECUTING_CODE_FORBIDDEN = - 1 << 63, ///< Page is forbidden from executing code (NXE bit in the EFER register has to be set) + 1UL << 63UL, ///< Page is forbidden from executing code (NXE bit in the EFER register has to be set) }; /** -- cgit v1.2.3 From 1d533cc10d926dde641af05537b540427c27bf64 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 15 Oct 2024 08:54:21 +0000 Subject: add assert import --- arch/x86_64/include/arch/memory/paging.hpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging.hpp b/arch/x86_64/include/arch/memory/paging.hpp index 25246f6..0b928b0 100644 --- a/arch/x86_64/include/arch/memory/paging.hpp +++ b/arch/x86_64/include/arch/memory/paging.hpp @@ -1,6 +1,8 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_HPP #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_HPP +#include "arch/exception_handling/assert.hpp" + #include "frame_allocator.hpp" namespace teachos::arch::memory -- cgit v1.2.3 From 429d99ca40254e9e19da938ff9f2065a543708cd Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 15 Oct 2024 09:05:37 +0000 Subject: rename contains_flags parameter --- arch/x86_64/include/arch/memory/multiboot.hpp | 4 ++-- arch/x86_64/include/arch/memory/paging.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp index c070e85..9a753fa 100644 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -180,10 +180,10 @@ namespace teachos::arch::memory * bits that are set in the given std::bitset also have to be set in the underlyng std::bitset. Any additional bits * that are set are not relevant. * - * @param flags Flags that we want to compare against and check if the underlying std::bitset has the same bits set. + * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. * @return Whether the given flags are a subset or equivalent with the underlying std::bitset */ - auto contains_flags(std::bitset<64U> b) const -> bool; + auto contains_flags(std::bitset<64U> other) const -> bool; /** * @brief Allows to compare the underlying std::bitset of two instances diff --git a/arch/x86_64/include/arch/memory/paging.hpp b/arch/x86_64/include/arch/memory/paging.hpp index 0b928b0..16fa476 100644 --- a/arch/x86_64/include/arch/memory/paging.hpp +++ b/arch/x86_64/include/arch/memory/paging.hpp @@ -86,10 +86,10 @@ namespace teachos::arch::memory * bits that are set in the given std::bitset also have to be set in the underlyng std::bitset. Any additional bits * that are set are not relevant. * - * @param flags Flags that we want to compare against and check if the underlying std::bitset has the same bits set. + * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. * @return Whether the given flags are a subset or equivalent with the underlying std::bitset */ - auto contains_flags(std::bitset<64U> b) const -> bool; + auto contains_flags(std::bitset<64U> other) const -> bool; private: /** -- cgit v1.2.3 From 0c4fd9eaed4a71975879aa83cd2da4b6266a64b5 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 15 Oct 2024 15:48:43 +0000 Subject: add 4th level page table --- arch/x86_64/include/arch/memory/paging.hpp | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging.hpp b/arch/x86_64/include/arch/memory/paging.hpp index 16fa476..7b705ac 100644 --- a/arch/x86_64/include/arch/memory/paging.hpp +++ b/arch/x86_64/include/arch/memory/paging.hpp @@ -91,6 +91,9 @@ namespace teachos::arch::memory */ auto contains_flags(std::bitset<64U> other) 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 flags by the operating system. + private: /** * @brief Extracts the physical address from the underlying bitset read from bit index 12 - 51. Is a 52 bit page @@ -100,9 +103,6 @@ namespace teachos::arch::memory * @return Extracted physical address of the next page or of the frame for P1 page tables. */ auto calculate_physical_address() const -> std::size_t; - - std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 9 - 11 and 52 - 62 can be freely - ///< used for additional flags by the operating system. }; /** @@ -115,6 +115,25 @@ namespace teachos::arch::memory */ auto zero_entries() -> void; + /** + * @brief Find and return the next table address + * + * The next table address is only valid if the corresponding entry is present + * and does not create a huge page + * + * @param index + * @return An optional of the address of the next page table or null + */ + auto next_table_address(std::size_t index) const -> std::optional; + + /** + * @brief Convert the address of a page_table into a page_table + * + * @param index + * @return An optional of the next page table or null + */ + auto next_table(size_t index) const -> std::optional; + /** * @brief Index operator overload to access specific entries directy * @@ -129,6 +148,7 @@ namespace teachos::arch::memory private: entry entries[PAGE_TABLE_ENTRY_COUNT]; + page_table const * p4 = reinterpret_cast(0xfffffffffffff000); }; } // namespace teachos::arch::memory -- cgit v1.2.3 From f56004a77314d4b4d68bfaf496fd7c6013ba7a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 16 Oct 2024 11:52:01 +0000 Subject: Adjust types --- arch/x86_64/include/arch/memory/paging.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging.hpp b/arch/x86_64/include/arch/memory/paging.hpp index 7b705ac..c13c3fe 100644 --- a/arch/x86_64/include/arch/memory/paging.hpp +++ b/arch/x86_64/include/arch/memory/paging.hpp @@ -91,9 +91,6 @@ namespace teachos::arch::memory */ auto contains_flags(std::bitset<64U> other) 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 flags by the operating system. - private: /** * @brief Extracts the physical address from the underlying bitset read from bit index 12 - 51. Is a 52 bit page @@ -103,6 +100,9 @@ namespace teachos::arch::memory * @return Extracted physical address of the next page or of the frame for P1 page tables. */ auto calculate_physical_address() const -> std::size_t; + + std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 9 - 11 and 52 - 62 can be freely + ///< used for additional flags by the operating system. }; /** @@ -132,7 +132,7 @@ namespace teachos::arch::memory * @param index * @return An optional of the next page table or null */ - auto next_table(size_t index) const -> std::optional; + auto next_table(std::size_t index) const -> std::optional; /** * @brief Index operator overload to access specific entries directy @@ -140,7 +140,7 @@ namespace teachos::arch::memory * @param index * @return The address of the accessed entry */ - entry & operator[](size_t index) + entry & operator[](std::size_t index) { arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); return entries[index]; -- cgit v1.2.3 From 934822e48a7c5a3e65ed74261ce5ab4315595f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 16 Oct 2024 13:33:23 +0000 Subject: Fix compilation issues with assigning values to page_map_variable address --- .../x86_64/include/arch/memory/frame_allocator.hpp | 27 ++++++++-------------- arch/x86_64/include/arch/memory/paging.hpp | 6 +---- 2 files changed, 10 insertions(+), 23 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/frame_allocator.hpp b/arch/x86_64/include/arch/memory/frame_allocator.hpp index 3d1f826..89f2570 100644 --- a/arch/x86_64/include/arch/memory/frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/frame_allocator.hpp @@ -119,16 +119,7 @@ namespace teachos::arch::memory * @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(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(); - } + std::size_t multiboot_end, memory_area * memory_areas, uint8_t area_count); /** * @brief Allocate memory by finding and returning a free physical_frame. @@ -171,14 +162,14 @@ namespace teachos::arch::memory */ auto choose_next_area() -> void; - physical_frame next_free_frame{0}; ///< The physical_frame after the last allocated one. - std::optional 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. + physical_frame next_free_frame; ///< The physical_frame after the last allocated one. + std::optional current_area; ///< 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/paging.hpp b/arch/x86_64/include/arch/memory/paging.hpp index c13c3fe..4092d18 100644 --- a/arch/x86_64/include/arch/memory/paging.hpp +++ b/arch/x86_64/include/arch/memory/paging.hpp @@ -140,11 +140,7 @@ namespace teachos::arch::memory * @param index * @return The address of the accessed entry */ - entry & operator[](std::size_t index) - { - arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); - return entries[index]; - } + entry & operator[](std::size_t index); private: entry entries[PAGE_TABLE_ENTRY_COUNT]; -- cgit v1.2.3 From 35e25757b6cffbcb2ff1eea8daf4c5f1ca421cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 16 Oct 2024 14:10:32 +0000 Subject: Adjust table accessing code to make it safer (always out of bounds checked) --- arch/x86_64/include/arch/memory/multiboot.hpp | 4 ++- arch/x86_64/include/arch/memory/paging.hpp | 43 +++++++++++++++++---------- 2 files changed, 31 insertions(+), 16 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp index 9a753fa..9cca8bc 100644 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -194,7 +194,9 @@ namespace teachos::arch::memory auto operator==(elf_section_flags const & other) const -> bool = default; private: - std::bitset<64U> flags; + std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 21 - 28 are reserved for operating + ///< system specific semantics and bits 29 - 32 are reserved for processor specific + ///< semantics. Bits 33 - 64 are unused for compatability with ELF32. }; /** diff --git a/arch/x86_64/include/arch/memory/paging.hpp b/arch/x86_64/include/arch/memory/paging.hpp index 4092d18..d55835e 100644 --- a/arch/x86_64/include/arch/memory/paging.hpp +++ b/arch/x86_64/include/arch/memory/paging.hpp @@ -110,41 +110,54 @@ namespace teachos::arch::memory */ struct page_table { + /** + * @brief Constructor. + */ + page_table(); + /** * @brief Set every entry of the page to unused */ auto zero_entries() -> void; /** - * @brief Find and return the next table address + * @brief Convert the address of a page_table into a page_table * - * The next table address is only valid if the corresponding entry is present - * and does not create a huge page + * @param index Index of the entry we want to access + * @return An optional of the next page table or null + */ + auto next_table(std::size_t index) const -> std::optional; + + /** + * @brief Index operator overload to access specific mutable entry directy * - * @param index - * @return An optional of the address of the next page table or null + * @param index Index of the entry we want to access and change + * @return Entry at the given table index */ - auto next_table_address(std::size_t index) const -> std::optional; + auto operator[](std::size_t index) -> entry &; /** - * @brief Convert the address of a page_table into a page_table + * @brief Index operator overload to access specific immutable entry directy * - * @param index - * @return An optional of the next page table or null + * @param index Index of the entry we want to access and only read + * @return Entry at the given table index */ - auto next_table(std::size_t index) const -> std::optional; + auto operator[](std::size_t index) const -> entry const &; + private: /** - * @brief Index operator overload to access specific entries directy + * @brief Find and return the next table address + * + * The next table address is only valid if the corresponding entry is present + * and does not create a huge page * * @param index - * @return The address of the accessed entry + * @return An optional of the address of the next page table or null */ - entry & operator[](std::size_t index); + auto next_table_address(std::size_t index) const -> std::optional; - private: entry entries[PAGE_TABLE_ENTRY_COUNT]; - page_table const * p4 = reinterpret_cast(0xfffffffffffff000); + page_table const * p4; }; } // namespace teachos::arch::memory -- cgit v1.2.3 From d539ed1f4f26a42959bcae6ea3050b7f99f5f872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 16 Oct 2024 14:30:04 +0000 Subject: Attempt to implement page table checks using templates --- arch/x86_64/include/arch/memory/paging.hpp | 83 ++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 16 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging.hpp b/arch/x86_64/include/arch/memory/paging.hpp index d55835e..4bbb0e0 100644 --- a/arch/x86_64/include/arch/memory/paging.hpp +++ b/arch/x86_64/include/arch/memory/paging.hpp @@ -105,28 +105,63 @@ namespace teachos::arch::memory ///< used for additional flags by the operating system. }; + enum level : uint8_t; + /** - * @brief A Page table containing 512 entries + * @brief A Page table containing 512 entries. */ + template struct page_table { + enum level : uint8_t + { + LEVEL1, + LEVEL2, + LEVEL3, + LEVEL4 + }; + /** * @brief Constructor. */ - page_table(); + page_table() + : entries() + , p4(reinterpret_cast(0xfffffffffffff000)) + { + // Nothing to do + } /** * @brief Set every entry of the page to unused */ - auto zero_entries() -> void; + auto zero_entries() -> void + { + constexpr size_t entry_amount = sizeof(entries) / sizeof(entries[0]); + for (size_t i = 0; i < entry_amount; ++i) + { + auto entry = entry.set_unused(); + } + } /** - * @brief Convert the address of a page_table into a page_table + * @brief Gets the complete next page table level from the given page table index. Meaning we use an index into a + * Level 4 page table to get the according Level 3 page table. * - * @param index Index of the entry we want to access - * @return An optional of the next page table or null + * @param table_index Index of this page table in the page table one level higher. + * @return Entire page table of the next level. */ - auto next_table(std::size_t index) const -> std::optional; + auto next_table(std::size_t table_index) const -> std::optional + requires(page_table_level > 0) + { + auto address = next_table_address(table_index); + + if (address.has_value()) + { + return reinterpret_cast(*address); + } + + return std::nullopt; + } /** * @brief Index operator overload to access specific mutable entry directy @@ -134,7 +169,13 @@ namespace teachos::arch::memory * @param index Index of the entry we want to access and change * @return Entry at the given table index */ - auto operator[](std::size_t index) -> entry &; + auto operator[](std::size_t index) -> entry & + { + // C array is not bounds checked, therefore we have to check ourselves, to ensure no out of bounds reads, which + // could be incredibly hard to debug later. + arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); + return entries[index]; + } /** * @brief Index operator overload to access specific immutable entry directy @@ -142,22 +183,32 @@ namespace teachos::arch::memory * @param index Index of the entry we want to access and only read * @return Entry at the given table index */ - auto operator[](std::size_t index) const -> entry const &; + auto operator[](std::size_t index) const -> entry const & { return this->operator[](index); } private: /** - * @brief Find and return the next table address + * @brief Calculates the address of the next page table level for the given table index. The next page table address + * is only valid if the corresponding entry is present and not a huge page. Meaning we use an index into a + * Level 4 page table to get the according Level 3 page table address. * - * The next table address is only valid if the corresponding entry is present - * and does not create a huge page - * - * @param index + * @param table_index Index of this page table in the page table one level higher. * @return An optional of the address of the next page table or null */ - auto next_table_address(std::size_t index) const -> std::optional; + auto next_table_address(std::size_t table_index) const -> std::optional + { + auto entry = this->operator[](table_index); + + if (entry.contains_flags(entry::PRESENT) && !entry.contains_flags(entry::HUGE_PAGE)) + { + std::size_t const table_address = reinterpret_cast(this); + return (table_address << 9) | (table_index << 12); + } + // TODO: Implement behaviour for huge pages currently not done + return std::nullopt; + } entry entries[PAGE_TABLE_ENTRY_COUNT]; - page_table const * p4; + page_table const * p4; }; } // namespace teachos::arch::memory -- cgit v1.2.3 From b865b36b38d951de28cc4df5fa67338b8245a1c3 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 17 Oct 2024 13:12:29 +0200 Subject: Implement support for `std::terminate` via `::abort` --- arch/x86_64/include/arch/exception_handling/assert.hpp | 7 ++++++- arch/x86_64/include/arch/exception_handling/panic.hpp | 13 +++++++++++++ arch/x86_64/include/arch/kernel/halt.hpp | 9 +++++++++ arch/x86_64/include/arch/video/vga/text.hpp | 5 +++++ 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 arch/x86_64/include/arch/exception_handling/panic.hpp create mode 100644 arch/x86_64/include/arch/kernel/halt.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/exception_handling/assert.hpp b/arch/x86_64/include/arch/exception_handling/assert.hpp index eba43ac..f355a61 100644 --- a/arch/x86_64/include/arch/exception_handling/assert.hpp +++ b/arch/x86_64/include/arch/exception_handling/assert.hpp @@ -1,3 +1,6 @@ +#ifndef TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_ASSERT_HPP +#define TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_ASSERT_HPP + namespace teachos::arch::exception_handling { /** @@ -8,4 +11,6 @@ namespace teachos::arch::exception_handling * @param message */ auto assert(bool condition, char const * message) -> void; -} // namespace teachos::arch::exception_handling \ No newline at end of file +} // namespace teachos::arch::exception_handling + +#endif \ No newline at end of file diff --git a/arch/x86_64/include/arch/exception_handling/panic.hpp b/arch/x86_64/include/arch/exception_handling/panic.hpp new file mode 100644 index 0000000..9566159 --- /dev/null +++ b/arch/x86_64/include/arch/exception_handling/panic.hpp @@ -0,0 +1,13 @@ +#ifndef TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_PANIC_HPP +#define TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_PANIC_HPP + +namespace teachos::arch::exception_handling +{ + /** + * @brief Print a kernel panic message and then halt the system. + */ + [[noreturn]] auto panic(char const * reason) -> void; + [[noreturn]] auto panic(char const * prefix, char const * reason) -> void; +} // namespace teachos::arch::exception_handling + +#endif \ No newline at end of file diff --git a/arch/x86_64/include/arch/kernel/halt.hpp b/arch/x86_64/include/arch/kernel/halt.hpp new file mode 100644 index 0000000..6c58938 --- /dev/null +++ b/arch/x86_64/include/arch/kernel/halt.hpp @@ -0,0 +1,9 @@ +#ifndef TEACHOS_ARCH_X86_64_KERNEL_HALT_HPP +#define TEACHOS_ARCH_X86_64_KERNEL_HALT_HPP + +namespace teachos::arch::kernel +{ + extern "C" [[noreturn]] auto halt() -> void; +} + +#endif \ No newline at end of file diff --git a/arch/x86_64/include/arch/video/vga/text.hpp b/arch/x86_64/include/arch/video/vga/text.hpp index cfafce0..690f4aa 100644 --- a/arch/x86_64/include/arch/video/vga/text.hpp +++ b/arch/x86_64/include/arch/video/vga/text.hpp @@ -99,6 +99,11 @@ namespace teachos::arch::video::vga::text */ auto cursor(bool enabled) -> void; + /** + * @brief Move the cursor to a new line, scrolling the buffer if necessary. + */ + auto newline() -> void; + /** * @brief Write a string of code points to the VGA text buffer. * -- cgit v1.2.3 From b6ce3a41fb53eabc6fde12c13f598d228435642a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 19 Oct 2024 11:25:08 +0000 Subject: Adjust memory_area structure to grub2 code --- arch/x86_64/include/arch/memory/multiboot.hpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp index 9cca8bc..8ecb1b5 100644 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -81,14 +81,24 @@ namespace teachos::arch::memory }; /** - * @brief Defines an entry in the entries array of the memory_map struct. + * @brief Defines an entry in the entries array of the memory_map struct. Has to have all padding stripped between the + * individual values, because the size of the entry needs to be exactly 24 bytes and not one byte more. See + * https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Packed-Structures.html for more information on the + * used attribute. */ - struct memory_area + struct __attribute__((packed)) memory_area { + uint32_t size; ///< TODO: Not clear what exactly the size signifies uint64_t base_address; ///< Base address the memory region starts at uint64_t area_length; ///< Size of the memory region, added to base_address results in the final address - alignas(8) memory_area_type type; ///< Specific type of memory the region can contain + memory_area_type type; ///< Specific type of memory the region can contain }; + /*struct memory_area + { + uint64_t base_address; ///< Base address the memory region starts at + uint64_t area_length; ///< Size of the memory region, added to base_address results in the final address + memory_area_type type; ///< Specific type of memory the region can contain + };*/ /** * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type -- cgit v1.2.3 From a2fdcea0d7615f8933401e45e0c64a2f618bb730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 19 Oct 2024 13:15:45 +0000 Subject: Move compelte multiboot2 code into seperate files and behaviour into seperate static class --- .../x86_64/include/arch/memory/frame_allocator.hpp | 84 ++----- arch/x86_64/include/arch/memory/multiboot.hpp | 262 --------------------- .../arch/memory/multiboot/elf_sybols_section.hpp | 157 ++++++++++++ arch/x86_64/include/arch/memory/multiboot/info.hpp | 62 +++++ .../include/arch/memory/multiboot/memory_map.hpp | 93 ++++++++ .../include/arch/memory/multiboot/reader.hpp | 50 ++++ arch/x86_64/include/arch/memory/paging.hpp | 5 + 7 files changed, 384 insertions(+), 329 deletions(-) delete mode 100644 arch/x86_64/include/arch/memory/multiboot.hpp create mode 100644 arch/x86_64/include/arch/memory/multiboot/elf_sybols_section.hpp create mode 100644 arch/x86_64/include/arch/memory/multiboot/info.hpp create mode 100644 arch/x86_64/include/arch/memory/multiboot/memory_map.hpp create mode 100644 arch/x86_64/include/arch/memory/multiboot/reader.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/frame_allocator.hpp b/arch/x86_64/include/arch/memory/frame_allocator.hpp index 89f2570..f1096d1 100644 --- a/arch/x86_64/include/arch/memory/frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/frame_allocator.hpp @@ -1,7 +1,8 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_FRAME_HPP #define TEACHOS_ARCH_X86_64_MEMORY_FRAME_HPP -#include "multiboot.hpp" +#include "multiboot/reader.hpp" + #include #include #include @@ -17,7 +18,7 @@ namespace teachos::arch::memory struct physical_frame { /** - * @brief Constructor + * @brief Constructor. * * @param frame_number Index number that should be assigned to this physical_frame. */ @@ -32,9 +33,9 @@ namespace teachos::arch::memory static auto containing_address(std::size_t address) -> physical_frame; /** - * @brief Evaluates the start address of the physical frame + * @brief Evaluates the start address of the physical frame. * - * @return start address of the physical frame + * @return start address of the physical frame. */ auto start_address() const -> uint64_t; @@ -58,51 +59,6 @@ namespace teachos::arch::memory { t.deallocate_frame() } -> std::same_as; }; - /** - * @brief Iterator for memory areas. - */ - struct memory_area_iterator - { - /** - * @brief Constructor. - * - * @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. - */ - memory_area & operator*() const; - - /** - * @brief Post increment operator. Returns a copy of the value - * - * @return Copy of the incremented underlying address. - */ - memory_area_iterator operator++(int); - - /** - * @brief Pre increment operator. Returns a reference to the changed value. - * - * @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. - */ - bool operator==(memory_area_iterator const & other) const = default; - - private: - memory_area * ptr; ///< Underlying address the iterator is currently pointing too. - }; - /** * @brief Allocates memory using memory areas read from the multiboot2 information pointer. */ @@ -111,15 +67,9 @@ namespace teachos::arch::memory /** * @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 mem_info Structure containg all relevant information to map and allocate memory */ - 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_frame_allocator(multiboot::memory_information mem_info); /** * @brief Allocate memory by finding and returning a free physical_frame. @@ -146,7 +96,7 @@ namespace teachos::arch::memory * * @return Iterator pointing to first element of the memory area. */ - auto begin() -> memory_area_iterator; + auto begin() -> multiboot::memory_area_iterator; /** * @brief Returns the iterator pointing to one past the last element of the memory area. @@ -154,7 +104,7 @@ namespace teachos::arch::memory * * @return Iterator pointing to one past the last element of the memory area. */ - auto end() -> memory_area_iterator; + auto end() -> multiboot::memory_area_iterator; private: /** @@ -162,14 +112,14 @@ namespace teachos::arch::memory */ auto choose_next_area() -> void; - physical_frame next_free_frame; ///< The physical_frame after the last allocated one. - std::optional current_area; ///< 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. + physical_frame next_free_frame; ///< The physical_frame after the last allocated one. + std::optional current_area; ///< The current memory area. + multiboot::memory_area_iterator area_begin; ///< Pointer to the first element of all memory areas. + multiboot::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 deleted file mode 100644 index 8ecb1b5..0000000 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ /dev/null @@ -1,262 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_HPP - -#include -#include - -namespace teachos::arch::memory -{ - /** - * @brief Defines all possible types a multiboot2 tag structure can have. - * See - * https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Boot-information-format for more information. - */ - enum class multi_boot_tag_type : uint32_t - { - END, ///< Signals final tag for the multiboot2 information structure - CMDLINE, ///< Contains the command line string - BOOT_LOADER_NAME, ///< Contains the name of the boot loader booting the kernel - MODULE, ///< Indicates the boot module which was loaded along the kernel image - BASIC_MEMORY_INFO, ///< Contains the amount of lower (0MB start address) and upper memory (1MB start address) - BOOTDEV, ///< Indicates which BIOS disk device the hoot loader has loaded the OS image from - MEMORY_MAP, ///< Describes the memory layout of the system with individual areas and their flags - VBE_INFO, ///< Includes information to access and utilize the device GPU - FRAMEBUFFER, ///< VBE framebuffer information - ELF_SECTIONS, ///< Includes list of all section headers from the loaded ELF kernel - APM_INFO, ///< Advanced Power Management information - EFI32, ///< EFI 32 bit system table pointer - EFI64, ///< EFI 64 bit system table pointer - SMBIOS, ///< Contains copy of all Sytem Management BIOS tables - ACPI_OLD, ///< Contains copy of RSDP as defined per ACPI1.0 specification - ACPI_NEW, ///< Contains copy of RSDP as defined per ACPI2.0 or later specification - NETWORK, ///< Contains network information specified specified as DHCP - EFI_MEMORY_MAP, ///< Contains EFI memory map - EFI_BS_NOT_TERMINATED, ///< Indicated ExitBootServies wasn't called - EFI32_IMAGE_HANDLE, ///< EFI 32 bit image handle pointer - EFI64_IMAGE_HANDLE, ///< EFI 64 bit imae handle pointer - LOAD_BASE_ADDRESS ///< Contains image load base physical address - }; - - /** - * @brief Basic structure that every entry in the multi_boot_tag array of the multi_boot_info struct has to begin - * with. - */ - struct multi_boot_tag - { - multi_boot_tag_type type; ///< Specific type of this multi_boot_tag entry, used to differentiate handling - uint32_t size; ///< Total size of this multi_boot_tag entry with all fields of the actual type - }; - - /** - * @brief Basic structure the multiboot_information_pointer points too and which contains all information of - * multiboot2 in the tags array of different types. The start as well as the content has to be 8 byte aligned. - */ - struct multi_boot_info - { - uint32_t total_size; ///< Total size of all multi_boot_tags and their data - alignas(8) struct multi_boot_tag tags; ///< Specific tags - }; - - /** - * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type - * multi_boot_tag_type::BASIC_MEMORY_INFO. - */ - struct memory_info - { - multi_boot_tag tag; ///< Basic multi_boot_tag information - uint32_t mem_lower; ///< Amount of lower memory (0MB start address) - uint32_t mem_upper; ///< Amount of upper memory (1MB start address) - }; - - /** - * @brief Defines all memory area types possible that the memory region can be in. - */ - enum class memory_area_type : uint32_t - { - AVAILABLE = 1, ///< Region is available for use by the OS - RESERVED, ///< Region is reserved by firmware or bootloader and should not be used by OS - ACPI_AVAILABLE, ///< Region is reclaimable by OS after ACPI event - RESERVED_HIBERNATION, ///< Region is used for Non-volatile Storage (NVS) - DEFECTIVE ///< Region is defective or unusable - }; - - /** - * @brief Defines an entry in the entries array of the memory_map struct. Has to have all padding stripped between the - * individual values, because the size of the entry needs to be exactly 24 bytes and not one byte more. See - * https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Packed-Structures.html for more information on the - * used attribute. - */ - struct __attribute__((packed)) memory_area - { - uint32_t size; ///< TODO: Not clear what exactly the size signifies - uint64_t base_address; ///< Base address the memory region starts at - uint64_t area_length; ///< Size of the memory region, added to base_address results in the final address - memory_area_type type; ///< Specific type of memory the region can contain - }; - /*struct memory_area - { - uint64_t base_address; ///< Base address the memory region starts at - uint64_t area_length; ///< Size of the memory region, added to base_address results in the final address - memory_area_type type; ///< Specific type of memory the region can contain - };*/ - - /** - * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type - * multi_boot_tag_type::MEMORY_MAP. - */ - struct memory_map - { - multi_boot_tag tag; ///< Basic multi_boot_tag information - uint32_t entry_size; ///< Size of each entry in the memory_area array. Guaranteed multiple of 8 - uint32_t entry_version; ///< Version of the entries, currently 0 - struct memory_area entries; ///< Specific memory regions - }; - - /** - * @brief Defines all elf section types an elf section header can have. See - * https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information. - */ - enum class elf_section_type : uint32_t - { - INACTIVE, ///< (SHT_NULL) Unused, meaning all values are zeroed out - PROGRAMM, ///< (SHT_PROGBITS) Program data (DATA, CODE) - SYMBOL_TABLE, ///< (SHT_SYMBTAB) Contains actual entries pointed to in symbol hash table - STRING_TABLE, ///< (SHT_STRTAB) Contains symbols, section and deubbging null-terminated strings - RELOCATION_ENTRY_WITH_ADDENDS, ///< (SHT_RELA) Only used on 64 bit systems - SYMBOL_HASH_TABLE, ///< (SHT_HASH) Hash table used by dynamic linker to locate symbols - DYNAMIC, ///< (SHT_DYNAMIC) Contains dynamic linking information - NOTE, ///< (SHT_NOTE) Stores information that marks files in some way - EMPTY, ///< (SHT_NOBITS) Program data section, that occupies no space in the file (.bss) - RELOCATION_ENTRY_WITHOUT_ADDENDS, ///< (SHT_REL) Only used on 32 bit systems - UNSPECIFIED, ///< (SHT_SHLIB) Reserved but has unspecified semantics - DYNAMIC_SYMBOL_TABLE, ///< (SHT_DYNSYM) Holds minimal set of symbols adequate for dynamic linking - INITALIZATION_FUNCTION_ARRAY = 14, ///< (SHT_INIT_ARRAY) Array of pointers to intialization functions () -> void - TERMINATION_FUNCTION_ARRAY, ///< (SHT_FINI_ARRAY) Array of pointers to termination functions () -> void - PRE_INITALIZATION_FUNCTION_ARRAY ///< (SHT_PRE_INIT_ARRAY) Array of pointers to functions invoked before other - ///< initalization functions () -> void - }; - - /** - * @brief Defines helper function for all states that the elf section flags of an elf section header can - * have. See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html - * See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information. - */ - struct elf_section_flags - { - /** - * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. - */ - enum bitset : uint32_t - { - WRITABLE = 1U << 0U, ///< (SHF_WRITE) Section is writable at runtime. If it isn't then the section - ///< is assumed to be READONLY and only that flag is shown in the objdump. - OCCUPIES_MEMORY = 1U << 1U, ///< (SHF_ALLOC) Section occupies memory during execution. - ///< ALLOC flag is shown in the objdump. - EXECUTABLE_CODE = 1U << 2U, ///< (SHF_EXECINSTR) Section is executable. CODE flag is shown in the object dump. - DUPLICATE_DATA = 1U << 4U, ///< (SHF_MERGE) Section might be merged with another section. - CONTAINS_STRING = 1U << 5U, ///< (SHF_STRINGS) Section contains null-terminated strings. - SECTION_HEADER_INFO_IS_SECTION_HEADER_TABLE_INDEX = - 1U << 6U, ///< (SHF_INFO_LINK) Section contains the section header table index in the (sh_info) - ///< additional_information variable. - PRESERVE_ORDERING_AFTER_COMBINATION = - 1U << 7U, ///< (SHF_LINK_ORDER) Section preserves order after combining with another section. - REQUIRES_SPECIAL_OS_PROCESSING = - 1U << 8U, ///< (SHF_OS_NONCONFORMING) Section requires non-standard OS specific handling of its code or - ///< data, which does not confirm to standard ELF specifications. - SECTION_GROUP_MEMBER = 1U << 9U, ///< (SHF_GROUP) Section is a member of a section group. - HOLDS_THREAD_LOCAL_DATA = 1U << 10U, ///< (SHF_TLS) Section holds thread-local data. - COMPRESSED = 1U << 11U, ///< (SHF_COMPRESSED) Section contains compressed data. - SPECIAL_ORDERING_REQUIREMENTS = - 1U << 30U, ///< (SHF_ORDERED) Section has special ordering requirements, meaning it - ///< should be ordered in relation to other sections of the same type - EXCLUDED_UNLESS_REFERENCED_OR_ALLOCATED = 1U << 31U, ///< (SHF_EXCLUDE)Section is excluded unless referenced or - ///< allocated, used for LTO (Link-Time Optimizations) - }; - - /** - * @brief Constructor. - * - * @param flags Actual value read from the elf section header, which should be converted into a std::bitset, to - * allow reading the state of single bits more easily. - */ - explicit elf_section_flags(uint64_t flags) - : flags(flags) - { - // Nothing to do - } - - /** - * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset, meaning that all - * bits that are set in the given std::bitset also have to be set in the underlyng std::bitset. Any additional bits - * that are set are not relevant. - * - * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. - * @return Whether the given flags are a subset or equivalent with the underlying std::bitset - */ - auto contains_flags(std::bitset<64U> other) const -> bool; - - /** - * @brief Allows to compare the underlying std::bitset of two instances - * - * @param other Other instance that we want to compare with - * @return Whether the underlying std::bitset of both types is the same - */ - auto operator==(elf_section_flags const & other) const -> bool = default; - - private: - std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 21 - 28 are reserved for operating - ///< system specific semantics and bits 29 - 32 are reserved for processor specific - ///< semantics. Bits 33 - 64 are unused for compatability with ELF32. - }; - - /** - * @brief Defines the data included in a section header, where each section has exactly one section header. - * See https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html for more information - */ - struct elf_section_header - { - uint32_t name_table_index; ///< Index into the section header string table, specifies the name of the section - elf_section_type type; ///< Categorizes the sections content and semantics - elf_section_flags flags; ///< 1-bit flgas that describe section attributes - uint64_t virtual_address; ///< If section appears in memory image of a process, gives address at which the sections - ///< first byte should reside, otherwise 0 - uint64_t file_offset; ///< Offset from the beginning of the file to the first byte in the section. SHT_NOBITS - ///< contains the conceptual placement instead (because it occupies no space in the file) - uint64_t section_size; ///< Complete section size in bytes, SHT_NOBITS may have non-zero value but will always - ///< occupy no space in the file - uint32_t other_section; ///< Section header table index link, behaviour varies on type - ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link - uint32_t additional_information; ///< Extra information, behaviour varies on type - ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link - uint64_t address_alignment; ///< Possible address alignment constraints. Value of virutal_address must be 0 % value - ///< of address_alignment. Value 0 or 1 mean no alignment constraints - uint64_t fixed_table_entry_size; ///< If sections holds table with fixed-sized entries, this gives the size in - ///< bytes of each entry - - /** - * @brief Detect whether a section header is inactive or not, should always be the case for the first entry in the - * sections table - * @return Whether the current section header is actually null or not, requires all fields besides section_size and - * other_section to contain 0 - */ - auto is_null() const -> bool; - }; - - /** - * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type - * multi_boot_tag_type::ELF_SECTIONS. - * The first section in the sections array will always be INACTIVE, there can only ever be one DYNAMIC section and - * only either one DYNAMIC_SYMBOL_TABLE or SYMBOL_TABLE. - */ - struct elf_symbols_section - { - multi_boot_tag tag; ///< Basic multi_boot_tag information - uint32_t number_of_sections; ///< Number of sections in the sections array - uint32_t entry_size; ///< Size of each entry in the sections array - uint32_t section_index; ///< Index to the string table used for symbol names - std::byte end; ///< Marks the end of the tag, used to mark the beginning of any additional data - ///< contained in the section, to ensure byte alignment is actually 4 byte - }; -} // namespace teachos::arch::memory - -#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/elf_sybols_section.hpp b/arch/x86_64/include/arch/memory/multiboot/elf_sybols_section.hpp new file mode 100644 index 0000000..88d211e --- /dev/null +++ b/arch/x86_64/include/arch/memory/multiboot/elf_sybols_section.hpp @@ -0,0 +1,157 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP + +#include "info.hpp" +#include +#include + +namespace teachos::arch::memory::multiboot +{ + /** + * @brief Defines all elf section types an elf section header can have. See + * https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information. + */ + enum class elf_section_type : uint32_t + { + INACTIVE, ///< (SHT_NULL) Unused, meaning all values are zeroed out + PROGRAMM, ///< (SHT_PROGBITS) Program data (DATA, CODE) + SYMBOL_TABLE, ///< (SHT_SYMBTAB) Contains actual entries pointed to in symbol hash table + STRING_TABLE, ///< (SHT_STRTAB) Contains symbols, section and deubbging null-terminated strings + RELOCATION_ENTRY_WITH_ADDENDS, ///< (SHT_RELA) Only used on 64 bit systems + SYMBOL_HASH_TABLE, ///< (SHT_HASH) Hash table used by dynamic linker to locate symbols + DYNAMIC, ///< (SHT_DYNAMIC) Contains dynamic linking information + NOTE, ///< (SHT_NOTE) Stores information that marks files in some way + EMPTY, ///< (SHT_NOBITS) Program data section, that occupies no space in the file (.bss) + RELOCATION_ENTRY_WITHOUT_ADDENDS, ///< (SHT_REL) Only used on 32 bit systems + UNSPECIFIED, ///< (SHT_SHLIB) Reserved but has unspecified semantics + DYNAMIC_SYMBOL_TABLE, ///< (SHT_DYNSYM) Holds minimal set of symbols adequate for dynamic linking + INITALIZATION_FUNCTION_ARRAY = 14, ///< (SHT_INIT_ARRAY) Array of pointers to intialization functions () -> void + TERMINATION_FUNCTION_ARRAY, ///< (SHT_FINI_ARRAY) Array of pointers to termination functions () -> void + PRE_INITALIZATION_FUNCTION_ARRAY ///< (SHT_PRE_INIT_ARRAY) Array of pointers to functions invoked before other + ///< initalization functions () -> void + }; + + /** + * @brief Defines helper function for all states that the elf section flags of an elf section header can + * have. See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html + * See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information. + */ + struct elf_section_flags + { + /** + * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + */ + enum bitset : uint32_t + { + WRITABLE = 1U << 0U, ///< (SHF_WRITE) Section is writable at runtime. If it isn't then the section + ///< is assumed to be READONLY and only that flag is shown in the objdump. + OCCUPIES_MEMORY = 1U << 1U, ///< (SHF_ALLOC) Section occupies memory during execution. + ///< ALLOC flag is shown in the objdump. + EXECUTABLE_CODE = 1U << 2U, ///< (SHF_EXECINSTR) Section is executable. CODE flag is shown in the object dump. + DUPLICATE_DATA = 1U << 4U, ///< (SHF_MERGE) Section might be merged with another section. + CONTAINS_STRING = 1U << 5U, ///< (SHF_STRINGS) Section contains null-terminated strings. + SECTION_HEADER_INFO_IS_SECTION_HEADER_TABLE_INDEX = + 1U << 6U, ///< (SHF_INFO_LINK) Section contains the section header table index in the (sh_info) + ///< additional_information variable. + PRESERVE_ORDERING_AFTER_COMBINATION = + 1U << 7U, ///< (SHF_LINK_ORDER) Section preserves order after combining with another section. + REQUIRES_SPECIAL_OS_PROCESSING = + 1U << 8U, ///< (SHF_OS_NONCONFORMING) Section requires non-standard OS specific handling of its code or + ///< data, which does not confirm to standard ELF specifications. + SECTION_GROUP_MEMBER = 1U << 9U, ///< (SHF_GROUP) Section is a member of a section group. + HOLDS_THREAD_LOCAL_DATA = 1U << 10U, ///< (SHF_TLS) Section holds thread-local data. + COMPRESSED = 1U << 11U, ///< (SHF_COMPRESSED) Section contains compressed data. + SPECIAL_ORDERING_REQUIREMENTS = + 1U << 30U, ///< (SHF_ORDERED) Section has special ordering requirements, meaning it + ///< should be ordered in relation to other sections of the same type + EXCLUDED_UNLESS_REFERENCED_OR_ALLOCATED = 1U << 31U, ///< (SHF_EXCLUDE)Section is excluded unless referenced or + ///< allocated, used for LTO (Link-Time Optimizations) + }; + + /** + * @brief Constructor. + * + * @param flags Actual value read from the elf section header, which should be converted into a std::bitset, to + * allow reading the state of single bits more easily. + */ + explicit elf_section_flags(uint64_t flags) + : flags(flags) + { + // Nothing to do + } + + /** + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset, meaning that all + * bits that are set in the given std::bitset also have to be set in the underlyng std::bitset. Any additional bits + * that are set are not relevant. + * + * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. + * @return Whether the given flags are a subset or equivalent with the underlying std::bitset + */ + auto contains_flags(std::bitset<64U> other) const -> bool; + + /** + * @brief Allows to compare the underlying std::bitset of two instances + * + * @param other Other instance that we want to compare with + * @return Whether the underlying std::bitset of both types is the same + */ + auto operator==(elf_section_flags const & other) const -> bool = default; + + private: + std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 21 - 28 are reserved for operating + ///< system specific semantics and bits 29 - 32 are reserved for processor specific + ///< semantics. Bits 33 - 64 are unused for compatability with ELF32. + }; + + /** + * @brief Defines the data included in a section header, where each section has exactly one section header. + * See https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html for more information + */ + struct elf_section_header + { + uint32_t name_table_index; ///< Index into the section header string table, specifies the name of the section + elf_section_type type; ///< Categorizes the sections content and semantics + elf_section_flags flags; ///< 1-bit flgas that describe section attributes + uint64_t virtual_address; ///< If section appears in memory image of a process, gives address at which the sections + ///< first byte should reside, otherwise 0 + uint64_t file_offset; ///< Offset from the beginning of the file to the first byte in the section. SHT_NOBITS + ///< contains the conceptual placement instead (because it occupies no space in the file) + uint64_t section_size; ///< Complete section size in bytes, SHT_NOBITS may have non-zero value but will always + ///< occupy no space in the file + uint32_t other_section; ///< Section header table index link, behaviour varies on type + ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link + uint32_t additional_information; ///< Extra information, behaviour varies on type + ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link + uint64_t address_alignment; ///< Possible address alignment constraints. Value of virutal_address must be 0 % value + ///< of address_alignment. Value 0 or 1 mean no alignment constraints + uint64_t fixed_table_entry_size; ///< If sections holds table with fixed-sized entries, this gives the size in + ///< bytes of each entry + + /** + * @brief Detect whether a section header is inactive or not, should always be the case for the first entry in the + * sections table + * @return Whether the current section header is actually null or not, requires all fields besides section_size and + * other_section to contain 0 + */ + auto is_null() const -> bool; + }; + + /** + * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type + * multi_boot_tag_type::ELF_SECTIONS. + * The first section in the sections array will always be INACTIVE, there can only ever be one DYNAMIC section and + * only either one DYNAMIC_SYMBOL_TABLE or SYMBOL_TABLE. + */ + struct elf_symbols_section_header + { + tag info; ///< Basic multi_boot_tag information + uint32_t number_of_sections; ///< Number of sections in the sections array + uint32_t entry_size; ///< Size of each entry in the sections array + uint32_t section_index; ///< Index to the string table used for symbol names + std::byte end; ///< Marks the end of the tag, used to mark the beginning of any additional data + ///< contained in the section, to ensure byte alignment is actually 4 byte + }; +} // namespace teachos::arch::memory::multiboot + +#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/info.hpp b/arch/x86_64/include/arch/memory/multiboot/info.hpp new file mode 100644 index 0000000..ca87834 --- /dev/null +++ b/arch/x86_64/include/arch/memory/multiboot/info.hpp @@ -0,0 +1,62 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_INFO_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_INFO_HPP + +#include + +namespace teachos::arch::memory::multiboot +{ + /** + * @brief Defines all possible types a multiboot2 tag structure can have. + * See + * https://github.com/rhboot/grub2/blob/fedora-39/include/multiboot2.h for more information on the structure of the + * tag headers and see https://github.com/rhboot/grub2/blob/fedora-39/include/multiboot.h for more information on the + * actual header contents and their following data. + */ + enum class tag_type : uint32_t + { + END, ///< Signals final tag for the multiboot2 information structure + CMDLINE, ///< Contains the command line string + BOOT_LOADER_NAME, ///< Contains the name of the boot loader booting the kernel + MODULE, ///< Indicates the boot module which was loaded along the kernel image + BASIC_MEMORY_INFO, ///< Contains the amount of lower (0MB start address) and upper memory (1MB start address) + BOOTDEV, ///< Indicates which BIOS disk device the hoot loader has loaded the OS image from + MEMORY_MAP, ///< Describes the memory layout of the system with individual areas and their flags + VBE_INFO, ///< Includes information to access and utilize the device GPU + FRAMEBUFFER, ///< VBE framebuffer information + ELF_SECTIONS, ///< Includes list of all section headers from the loaded ELF kernel + APM_INFO, ///< Advanced Power Management information + EFI32, ///< EFI 32 bit system table pointer + EFI64, ///< EFI 64 bit system table pointer + SMBIOS, ///< Contains copy of all Sytem Management BIOS tables + ACPI_OLD, ///< Contains copy of RSDP as defined per ACPI1.0 specification + ACPI_NEW, ///< Contains copy of RSDP as defined per ACPI2.0 or later specification + NETWORK, ///< Contains network information specified specified as DHCP + EFI_MEMORY_MAP, ///< Contains EFI memory map + EFI_BS_NOT_TERMINATED, ///< Indicated ExitBootServies wasn't called + EFI32_IMAGE_HANDLE, ///< EFI 32 bit image handle pointer + EFI64_IMAGE_HANDLE, ///< EFI 64 bit imae handle pointer + LOAD_BASE_ADDRESS ///< Contains image load base physical address + }; + + /** + * @brief Basic structure that every entry in the multi_boot_tag array of the multi_boot_info struct has to begin + * with. + */ + struct tag + { + tag_type type; ///< Specific type of this multi_boot_tag entry, used to differentiate handling + uint32_t size; ///< Total size of this multi_boot_tag entry with all fields of the actual type + }; + + /** + * @brief Basic structure the multiboot_information_pointer points too and which contains all information of + * multiboot2 in the tags array of different types. The start as well as the content has to be 8 byte aligned. + */ + struct info_header + { + uint32_t total_size; ///< Total size of all multiboot::tags and their data + alignas(8) struct tag tags; ///< Specific tags + }; +} // namespace teachos::arch::memory::multiboot + +#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_INFO_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp new file mode 100644 index 0000000..4dc11cf --- /dev/null +++ b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp @@ -0,0 +1,93 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP + +#include "info.hpp" +#include + +namespace teachos::arch::memory::multiboot +{ + /** + * @brief Defines all memory area types possible that the memory region can be in. + */ + enum class memory_area_type : uint32_t + { + AVAILABLE = 1, ///< Region is available for use by the OS + RESERVED, ///< Region is reserved by firmware or bootloader and should not be used by OS + ACPI_AVAILABLE, ///< Region is reclaimable by OS after ACPI event + RESERVED_HIBERNATION, ///< Region is used for Non-volatile Storage (NVS) + DEFECTIVE ///< Region is defective or unusable + }; + + /** + * @brief Defines an entry in the entries array of the memory_map struct. Has to have all padding stripped between the + * individual values, because the size of the entry needs to be exactly 24 bytes and not one byte more. See + * https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Packed-Structures.html for more information on the + * used attribute. + */ + struct __attribute__((packed)) memory_area + { + uint32_t size; ///< Size of this structure in bytes + uint64_t base_address; ///< Base address the memory region starts at + uint64_t area_length; ///< Size of the memory region, added to base_address results in the final address + memory_area_type type; ///< Specific type of memory the region can contain + }; + + /** + * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type + * multi_boot_tag_type::MEMORY_MAP. + */ + struct memory_map_header + { + tag info; ///< Basic multi_boot_tag information + uint32_t entry_size; ///< Size of each entry in the memory_area array. Guaranteed multiple of 8 + uint32_t entry_version; ///< Version of the entries, currently 0 + struct memory_area entries; ///< Specific memory regions + }; + + /** + * @brief Iterator for memory areas. + */ + struct memory_area_iterator + { + /** + * @brief Constructor. + * + * @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. + */ + memory_area & operator*() const; + + /** + * @brief Post increment operator. Returns a copy of the value + * + * @return Copy of the incremented underlying address. + */ + memory_area_iterator operator++(int); + + /** + * @brief Pre increment operator. Returns a reference to the changed value. + * + * @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. + */ + bool operator==(memory_area_iterator const & other) const = default; + + private: + memory_area * ptr; ///< Underlying address the iterator is currently pointing too. + }; +} // namespace teachos::arch::memory::multiboot + +#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/reader.hpp b/arch/x86_64/include/arch/memory/multiboot/reader.hpp new file mode 100644 index 0000000..14086a7 --- /dev/null +++ b/arch/x86_64/include/arch/memory/multiboot/reader.hpp @@ -0,0 +1,50 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP + +#include "elf_sybols_section.hpp" +#include "memory_map.hpp" +#include + +namespace teachos::arch::memory::multiboot +{ + /** + * @brief Contains all relevant information to map and allocate memory that is read from the multiboot2 information + * structure. + */ + struct memory_information + { + std::size_t kernel_start; ///< Start address of the kernel code in memory. + std::size_t kernel_end; ///< End address of the kernel code in memory. + std::size_t multiboot_start; ///< Start address of the multiboot code in memory. + std::size_t multiboot_end; ///< End address of the multiboot code in memory. + memory_area * memory_areas; ///< Non-owning pointer to the first element of all memory areas. + uint8_t area_count; ///< Amount of total entries in the memory_areas array. + }; + + /** + * @brief Reads the relevant multiboot2 information data from memory. This is done using the + * multiboot_information_pointer, which marks the start of the multiboot2 data. The indivdual headers we have to read + * are 8 byte aligned, whereas the data contained in those headers does not have to be. All sections that are read + * additionaly receive some sanity to ensure the read address is actually pointing to the expected structure, if they + * are not this method will assert. + * + * The memory_information variables are calcualted like this: + * - kernel_start: Calculated by getting the lowest address specified in the elf symbols headers. + * - kernel_end: Calculated by getting the highest address specified in the elf symbols headers and adding the length + * of that section. + * - multiboot_start: Calcualted by simply getting the value of the multiboot information pointer, because it already + * contains the address pointint to the start of the multiboot2 data. + * - multiboot_end: Calcualted by getting the value of the multiboot information pointer and adding the total size of + * the complete multiboot2 data + * - memory_areas: Calculated by simply accessing the address of the entries variable in the memory map header + * structure. + * - area_count: Calculated by subtracing the memory map header size from the total tag size, which results in the + * remaining size (size of the entries array), this size is then divided by the size of one entry in that array, which + * should be 24 bytes. + * + * @return Relevant data read from multiboot2. + */ + auto read_multiboot2() -> memory_information; +} // namespace teachos::arch::memory::multiboot + +#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP diff --git a/arch/x86_64/include/arch/memory/paging.hpp b/arch/x86_64/include/arch/memory/paging.hpp index 4bbb0e0..04c2065 100644 --- a/arch/x86_64/include/arch/memory/paging.hpp +++ b/arch/x86_64/include/arch/memory/paging.hpp @@ -4,6 +4,7 @@ #include "arch/exception_handling/assert.hpp" #include "frame_allocator.hpp" +#include namespace teachos::arch::memory { @@ -113,6 +114,10 @@ namespace teachos::arch::memory template struct page_table { + /** + * @brief Level of the page table, level 1 should not be able to call next_table anymore, because it would result in + * attempting to access memory that it should not. + */ enum level : uint8_t { LEVEL1, -- cgit v1.2.3 From 675f38d6733fb19b4ffc7e9fbddb93acdd1d1e31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 19 Oct 2024 14:40:25 +0000 Subject: Seperate allocation and paging code into multiple files as well --- .../arch/memory/allocator/area_frame_allocator.hpp | 75 +++++++ .../arch/memory/allocator/physical_frame.hpp | 52 +++++ .../x86_64/include/arch/memory/frame_allocator.hpp | 126 ------------ arch/x86_64/include/arch/memory/paging.hpp | 220 --------------------- .../include/arch/memory/paging/page_entry.hpp | 90 +++++++++ .../include/arch/memory/paging/page_table.hpp | 100 ++++++++++ .../include/arch/memory/paging/virtual_page.hpp | 27 +++ 7 files changed, 344 insertions(+), 346 deletions(-) create mode 100644 arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp create mode 100644 arch/x86_64/include/arch/memory/allocator/physical_frame.hpp delete mode 100644 arch/x86_64/include/arch/memory/frame_allocator.hpp delete mode 100644 arch/x86_64/include/arch/memory/paging.hpp create mode 100644 arch/x86_64/include/arch/memory/paging/page_entry.hpp create mode 100644 arch/x86_64/include/arch/memory/paging/page_table.hpp create mode 100644 arch/x86_64/include/arch/memory/paging/virtual_page.hpp (limited to 'arch/x86_64/include') 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 new file mode 100644 index 0000000..c9d4e7f --- /dev/null +++ b/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp @@ -0,0 +1,75 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP + +#include "arch/memory/multiboot/reader.hpp" + +#include "physical_frame.hpp" +#include + +namespace teachos::arch::memory::allocator +{ + /** + * @brief Allocates memory using memory areas read from the multiboot2 information pointer. + */ + struct area_frame_allocator + { + /** + * @brief Constructor + * + * @param mem_info Structure containg all relevant information to map and allocate memory + */ + area_frame_allocator(multiboot::memory_information mem_info); + + /** + * @brief Allocate memory by finding and returning a free physical_frame. + * + * 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 + */ + auto allocate_frame() -> std::optional; + + /** + * @brief Deallocates a previously allocated physical_frame. + * + * @param physical_frame Previously allocated physical_frame that should be allocated. + */ + 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. + * + * @return Iterator pointing to first element of the memory area. + */ + auto begin() -> multiboot::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. + * + * @return Iterator pointing to one past the last element of the memory area. + */ + auto end() -> multiboot::memory_area_iterator; + + private: + /** + * @brief Find the next memory area and write it into current_area. + */ + auto choose_next_area() -> void; + + physical_frame next_free_frame; ///< The physical_frame after the last allocated one. + std::optional current_area; ///< The current memory area. + multiboot::memory_area_iterator area_begin; ///< Pointer to the first element of all memory areas. + multiboot::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::allocator + +#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 new file mode 100644 index 0000000..5e99d10 --- /dev/null +++ b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp @@ -0,0 +1,52 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP + +#include +#include + +namespace teachos::arch::memory::allocator +{ + /** + * @brief Specific physical frame containing helper functions to determine if a specific address is in that + * physical frame or not. + */ + struct physical_frame + { + /** + * @brief Constructor. + * + * @param frame_number Index number that should be assigned to this physical_frame. + */ + explicit physical_frame(std::size_t frame_number); + + /** + * @brief Returns the physical_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) -> physical_frame; + + /** + * @brief Evaluates the start address of the physical frame. + * + * @return start address of the physical frame. + */ + auto start_address() const -> uint64_t; + + /** + * @brief Defaulted equals operator. + */ + constexpr auto operator==(const physical_frame & other) const -> bool = default; + + /** + * @brief Defaulted three-way comparsion operator. + */ + constexpr auto operator<=>(const physical_frame & 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. + }; +} // namespace teachos::arch::memory::allocator + +#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP diff --git a/arch/x86_64/include/arch/memory/frame_allocator.hpp b/arch/x86_64/include/arch/memory/frame_allocator.hpp deleted file mode 100644 index f1096d1..0000000 --- a/arch/x86_64/include/arch/memory/frame_allocator.hpp +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_FRAME_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_FRAME_HPP - -#include "multiboot/reader.hpp" - -#include -#include -#include - -namespace teachos::arch::memory -{ - constexpr std::size_t 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 Constructor. - * - * @param frame_number Index number that should be assigned to this physical_frame. - */ - explicit physical_frame(std::size_t frame_number); - - /** - * @brief Returns the physical_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) -> physical_frame; - - /** - * @brief Evaluates the start address of the physical frame. - * - * @return start address of the physical frame. - */ - auto start_address() const -> uint64_t; - - /** - * @brief Defaulted equals operator. - */ - constexpr auto operator==(const physical_frame & other) const -> bool = default; - - /** - * @brief Defaulted three-way comparsion operator. - */ - constexpr auto operator<=>(const physical_frame & 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. - }; - - template - concept FrameAllocator = requires(T t) { - { t.allocate_frame() } -> std::same_as>; - { t.deallocate_frame() } -> std::same_as; - }; - - /** - * @brief Allocates memory using memory areas read from the multiboot2 information pointer. - */ - struct area_frame_allocator - { - /** - * @brief Constructor - * - * @param mem_info Structure containg all relevant information to map and allocate memory - */ - area_frame_allocator(multiboot::memory_information mem_info); - - /** - * @brief Allocate memory by finding and returning a free physical_frame. - * - * 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 - */ - auto allocate_frame() -> std::optional; - - /** - * @brief Deallocates a previously allocated physical_frame. - * - * @param physical_frame Previously allocated physical_frame that should be allocated. - */ - 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. - * - * @return Iterator pointing to first element of the memory area. - */ - auto begin() -> multiboot::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. - * - * @return Iterator pointing to one past the last element of the memory area. - */ - auto end() -> multiboot::memory_area_iterator; - - private: - /** - * @brief Find the next memory area and write it into current_area. - */ - auto choose_next_area() -> void; - - physical_frame next_free_frame; ///< The physical_frame after the last allocated one. - std::optional current_area; ///< The current memory area. - multiboot::memory_area_iterator area_begin; ///< Pointer to the first element of all memory areas. - multiboot::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 - -#endif // TEACHOS_ARCH_X86_64_MEMORY_FRAME_HPP diff --git a/arch/x86_64/include/arch/memory/paging.hpp b/arch/x86_64/include/arch/memory/paging.hpp deleted file mode 100644 index 04c2065..0000000 --- a/arch/x86_64/include/arch/memory/paging.hpp +++ /dev/null @@ -1,220 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_HPP - -#include "arch/exception_handling/assert.hpp" - -#include "frame_allocator.hpp" -#include - -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 Possible set bits in our underlying std::bitset and the meaning when they are set. - */ - enum bitset : uint64_t - { - PRESENT = 1UL << 0UL, ///< Page is in memory and therefore present. - ///< is assumed to be READONLY and only that flag is shown in the objdump. - WRITABLE = 1UL << 1UL, ///< It is possible to write to the page. - USER_ACCESIBLE = 1UL << 2UL, ///< Page can be accessed in user mode instead of only in kernel mode code. - WRITE_THROUGH_CACHING = 1UL << 3UL, ///< Write to the page go directly to memory instead of the cache. - DISABLED_CACHING = 1UL << 4UL, ///< Page uses caching. - ACCESSED = 1UL << 5UL, ///< Page is currently in use. - DIRTY = 1UL << 6UL, ///< Page has been writen too. - HUGE_PAGE = 1UL << 7UL, ///< Page is huge (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. - GLOBAL = 1UL << 8UL, ///< Page is not flushed from caches on address space switches (PGE bit of CR4 register - ///< has to be set) - EXECUTING_CODE_FORBIDDEN = - 1UL << 63UL, ///< Page is forbidden from executing code (NXE bit in the EFER register has to be set) - }; - - /** - * @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 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; - - /** - * @brief Copies the address from the given physical frame into the underlying std::bitset so future calls to - * calculate_physical_address() will return the new address instead of the old one. - * - * @param frame Physical frame that contains the address we want to copy into our underlying std::bitset. - */ - auto set_address(physical_frame frame) -> void; - - /** - * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset, meaning that all - * bits that are set in the given std::bitset also have to be set in the underlyng std::bitset. Any additional bits - * that are set are not relevant. - * - * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. - * @return Whether the given flags are a subset or equivalent with the underlying std::bitset - */ - auto contains_flags(std::bitset<64U> other) const -> bool; - - 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; - - std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 9 - 11 and 52 - 62 can be freely - ///< used for additional flags by the operating system. - }; - - enum level : uint8_t; - - /** - * @brief A Page table containing 512 entries. - */ - template - struct page_table - { - /** - * @brief Level of the page table, level 1 should not be able to call next_table anymore, because it would result in - * attempting to access memory that it should not. - */ - enum level : uint8_t - { - LEVEL1, - LEVEL2, - LEVEL3, - LEVEL4 - }; - - /** - * @brief Constructor. - */ - page_table() - : entries() - , p4(reinterpret_cast(0xfffffffffffff000)) - { - // Nothing to do - } - - /** - * @brief Set every entry of the page to unused - */ - auto zero_entries() -> void - { - constexpr size_t entry_amount = sizeof(entries) / sizeof(entries[0]); - for (size_t i = 0; i < entry_amount; ++i) - { - auto entry = entry.set_unused(); - } - } - - /** - * @brief Gets the complete next page table level from the given page table index. Meaning we use an index into a - * Level 4 page table to get the according Level 3 page table. - * - * @param table_index Index of this page table in the page table one level higher. - * @return Entire page table of the next level. - */ - auto next_table(std::size_t table_index) const -> std::optional - requires(page_table_level > 0) - { - auto address = next_table_address(table_index); - - if (address.has_value()) - { - return reinterpret_cast(*address); - } - - return std::nullopt; - } - - /** - * @brief Index operator overload to access specific mutable entry directy - * - * @param index Index of the entry we want to access and change - * @return Entry at the given table index - */ - auto operator[](std::size_t index) -> entry & - { - // C array is not bounds checked, therefore we have to check ourselves, to ensure no out of bounds reads, which - // could be incredibly hard to debug later. - arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); - return entries[index]; - } - - /** - * @brief Index operator overload to access specific immutable entry directy - * - * @param index Index of the entry we want to access and only read - * @return Entry at the given table index - */ - auto operator[](std::size_t index) const -> entry const & { return this->operator[](index); } - - private: - /** - * @brief Calculates the address of the next page table level for the given table index. The next page table address - * is only valid if the corresponding entry is present and not a huge page. Meaning we use an index into a - * Level 4 page table to get the according Level 3 page table address. - * - * @param table_index Index of this page table in the page table one level higher. - * @return An optional of the address of the next page table or null - */ - auto next_table_address(std::size_t table_index) const -> std::optional - { - auto entry = this->operator[](table_index); - - if (entry.contains_flags(entry::PRESENT) && !entry.contains_flags(entry::HUGE_PAGE)) - { - std::size_t const table_address = reinterpret_cast(this); - return (table_address << 9) | (table_index << 12); - } - // TODO: Implement behaviour for huge pages currently not done - return std::nullopt; - } - - entry entries[PAGE_TABLE_ENTRY_COUNT]; - page_table const * p4; - }; -} // namespace teachos::arch::memory - -#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_HPP diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp new file mode 100644 index 0000000..a40e764 --- /dev/null +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -0,0 +1,90 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_ENTRY_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_ENTRY_HPP + +#include "arch/memory/allocator/physical_frame.hpp" + +#include +#include + +namespace teachos::arch::memory::paging +{ + /** + * @brief Marks a specific entry in an actual page table. + */ + struct entry + { + /** + * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + */ + enum bitset : uint64_t + { + PRESENT = 1UL << 0UL, ///< Page is in memory and therefore present. + ///< is assumed to be READONLY and only that flag is shown in the objdump. + WRITABLE = 1UL << 1UL, ///< It is possible to write to the page. + USER_ACCESIBLE = 1UL << 2UL, ///< Page can be accessed in user mode instead of only in kernel mode code. + WRITE_THROUGH_CACHING = 1UL << 3UL, ///< Write to the page go directly to memory instead of the cache. + DISABLED_CACHING = 1UL << 4UL, ///< Page uses caching. + ACCESSED = 1UL << 5UL, ///< Page is currently in use. + DIRTY = 1UL << 6UL, ///< Page has been writen too. + HUGE_PAGE = 1UL << 7UL, ///< Page is huge (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. + GLOBAL = 1UL << 8UL, ///< Page is not flushed from caches on address space switches (PGE bit of CR4 register + ///< has to be set) + EXECUTING_CODE_FORBIDDEN = + 1UL << 63UL, ///< Page is forbidden from executing code (NXE bit in the EFER register has to be set) + }; + + /** + * @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 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; + + /** + * @brief Copies the address from the given physical frame into the underlying std::bitset so future calls to + * calculate_physical_address() will return the new address instead of the old one. + * + * @param frame Physical frame that contains the address we want to copy into our underlying std::bitset. + */ + auto set_address(allocator::physical_frame frame) -> void; + + /** + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset, meaning that all + * bits that are set in the given std::bitset also have to be set in the underlyng std::bitset. Any additional bits + * that are set are not relevant. + * + * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. + * @return Whether the given flags are a subset or equivalent with the underlying std::bitset + */ + auto contains_flags(std::bitset<64U> other) const -> bool; + + 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; + + std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 9 - 11 and 52 - 62 can be freely + ///< used for additional flags by the operating system. + }; +} // namespace teachos::arch::memory::paging + +#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_ENTRY_HPP \ No newline at end of file diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp new file mode 100644 index 0000000..32e49e5 --- /dev/null +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -0,0 +1,100 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP + +#include "page_entry.hpp" + +namespace teachos::arch::memory::paging +{ + namespace + { + constexpr std::size_t PAGE_TABLE_ENTRY_COUNT = 512U; ///< Default entry count of a page table in x86_84 is 512. + } + + /** + * @brief Actual data that is contained in every page table, this is the structure we cast a specific address too, + * because it consists of x amount os entries, which is a simple address. + */ + struct table_content + { + entry entries[PAGE_TABLE_ENTRY_COUNT]; ///< Entries containing addresses to page tables of a level below or actual + ///< virtual addresses for the level 1 page table. + }; + + /** + * @brief A Page table containing 512 entries. + */ + struct page_table + { + /** + * @brief Level of the page table, level 1 should not be able to call next_table anymore, because it would result in + * attempting to access memory that it should not. + */ + enum level : uint8_t + { + LEVEL1, + LEVEL2, + LEVEL3, + LEVEL4 + }; + + /** + * @brief Constructor. Automatically starts on the fixed address of the Level 4 page table. + */ + page_table(); + + /** + * @brief Set every entry of the page to unused. + */ + auto zero_entries() -> void; + + /** + * @brief Gets the complete next page table level from the given page table index. Meaning we use an index into a + * Level 4 page table to get the according Level 3 page table. When using this on an a level 1 page table it will + * cause an assertion. + * + * @param table_index Index of this page table in the page table one level higher. + */ + auto next_table(std::size_t table_index) -> void; + + /** + * @brief Index operator overload to access specific mutable entry directy. + * + * @param index Index of the entry we want to access and change. + * @return Entry at the given table index. + */ + auto operator[](std::size_t index) -> entry &; + + /** + * @brief Index operator overload to access specific immutable entry directy. + * + * @param index Index of the entry we want to access and only read. + * @return Entry at the given table index. + */ + auto operator[](std::size_t index) const -> entry const &; + + private: + /** + * @brief Constructor. Used internally to create new page tables. + * + * @param new_level New level of the page table. + * @param new_table New table data contained in the page table. + */ + page_table(level new_level, table_content * new_table); + + /** + * @brief Calculates the address of the next page table level for the given table index. The next page table address + * is only valid if the corresponding entry is present and not a huge page. Meaning we use an index into a + * Level 4 page table to get the according Level 3 page table address. + * + * @param table_index Index of this page table in the page table one level higher. + * @return An optional of the address of the next page table or null. + */ + auto next_table_address(std::size_t table_index) const -> std::optional; + + level current_level; ///< Current level of the page table, used to ensure next_table() is never called with a level + ///< 1 page table + table_content * current_table; ///< Current table we are accessing and indexing. + }; +} // namespace teachos::arch::memory::paging + +#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP \ No newline at end of file diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp new file mode 100644 index 0000000..12af510 --- /dev/null +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -0,0 +1,27 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP + +#include + +namespace teachos::arch::memory::paging +{ + /** + * @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; + }; +} // namespace teachos::arch::memory::paging + +#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP \ No newline at end of file -- cgit v1.2.3 From 7ca089125b8c5e55dd584648cd33612883cc004d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 06:26:58 +0000 Subject: Fix typo in file name --- .../arch/memory/multiboot/elf_sybols_section.hpp | 157 --------------------- .../arch/memory/multiboot/elf_symbols_section.hpp | 157 +++++++++++++++++++++ .../include/arch/memory/multiboot/reader.hpp | 2 +- .../include/arch/memory/paging/page_table.hpp | 6 +- 4 files changed, 161 insertions(+), 161 deletions(-) delete mode 100644 arch/x86_64/include/arch/memory/multiboot/elf_sybols_section.hpp create mode 100644 arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot/elf_sybols_section.hpp b/arch/x86_64/include/arch/memory/multiboot/elf_sybols_section.hpp deleted file mode 100644 index 88d211e..0000000 --- a/arch/x86_64/include/arch/memory/multiboot/elf_sybols_section.hpp +++ /dev/null @@ -1,157 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP - -#include "info.hpp" -#include -#include - -namespace teachos::arch::memory::multiboot -{ - /** - * @brief Defines all elf section types an elf section header can have. See - * https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information. - */ - enum class elf_section_type : uint32_t - { - INACTIVE, ///< (SHT_NULL) Unused, meaning all values are zeroed out - PROGRAMM, ///< (SHT_PROGBITS) Program data (DATA, CODE) - SYMBOL_TABLE, ///< (SHT_SYMBTAB) Contains actual entries pointed to in symbol hash table - STRING_TABLE, ///< (SHT_STRTAB) Contains symbols, section and deubbging null-terminated strings - RELOCATION_ENTRY_WITH_ADDENDS, ///< (SHT_RELA) Only used on 64 bit systems - SYMBOL_HASH_TABLE, ///< (SHT_HASH) Hash table used by dynamic linker to locate symbols - DYNAMIC, ///< (SHT_DYNAMIC) Contains dynamic linking information - NOTE, ///< (SHT_NOTE) Stores information that marks files in some way - EMPTY, ///< (SHT_NOBITS) Program data section, that occupies no space in the file (.bss) - RELOCATION_ENTRY_WITHOUT_ADDENDS, ///< (SHT_REL) Only used on 32 bit systems - UNSPECIFIED, ///< (SHT_SHLIB) Reserved but has unspecified semantics - DYNAMIC_SYMBOL_TABLE, ///< (SHT_DYNSYM) Holds minimal set of symbols adequate for dynamic linking - INITALIZATION_FUNCTION_ARRAY = 14, ///< (SHT_INIT_ARRAY) Array of pointers to intialization functions () -> void - TERMINATION_FUNCTION_ARRAY, ///< (SHT_FINI_ARRAY) Array of pointers to termination functions () -> void - PRE_INITALIZATION_FUNCTION_ARRAY ///< (SHT_PRE_INIT_ARRAY) Array of pointers to functions invoked before other - ///< initalization functions () -> void - }; - - /** - * @brief Defines helper function for all states that the elf section flags of an elf section header can - * have. See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html - * See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information. - */ - struct elf_section_flags - { - /** - * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. - */ - enum bitset : uint32_t - { - WRITABLE = 1U << 0U, ///< (SHF_WRITE) Section is writable at runtime. If it isn't then the section - ///< is assumed to be READONLY and only that flag is shown in the objdump. - OCCUPIES_MEMORY = 1U << 1U, ///< (SHF_ALLOC) Section occupies memory during execution. - ///< ALLOC flag is shown in the objdump. - EXECUTABLE_CODE = 1U << 2U, ///< (SHF_EXECINSTR) Section is executable. CODE flag is shown in the object dump. - DUPLICATE_DATA = 1U << 4U, ///< (SHF_MERGE) Section might be merged with another section. - CONTAINS_STRING = 1U << 5U, ///< (SHF_STRINGS) Section contains null-terminated strings. - SECTION_HEADER_INFO_IS_SECTION_HEADER_TABLE_INDEX = - 1U << 6U, ///< (SHF_INFO_LINK) Section contains the section header table index in the (sh_info) - ///< additional_information variable. - PRESERVE_ORDERING_AFTER_COMBINATION = - 1U << 7U, ///< (SHF_LINK_ORDER) Section preserves order after combining with another section. - REQUIRES_SPECIAL_OS_PROCESSING = - 1U << 8U, ///< (SHF_OS_NONCONFORMING) Section requires non-standard OS specific handling of its code or - ///< data, which does not confirm to standard ELF specifications. - SECTION_GROUP_MEMBER = 1U << 9U, ///< (SHF_GROUP) Section is a member of a section group. - HOLDS_THREAD_LOCAL_DATA = 1U << 10U, ///< (SHF_TLS) Section holds thread-local data. - COMPRESSED = 1U << 11U, ///< (SHF_COMPRESSED) Section contains compressed data. - SPECIAL_ORDERING_REQUIREMENTS = - 1U << 30U, ///< (SHF_ORDERED) Section has special ordering requirements, meaning it - ///< should be ordered in relation to other sections of the same type - EXCLUDED_UNLESS_REFERENCED_OR_ALLOCATED = 1U << 31U, ///< (SHF_EXCLUDE)Section is excluded unless referenced or - ///< allocated, used for LTO (Link-Time Optimizations) - }; - - /** - * @brief Constructor. - * - * @param flags Actual value read from the elf section header, which should be converted into a std::bitset, to - * allow reading the state of single bits more easily. - */ - explicit elf_section_flags(uint64_t flags) - : flags(flags) - { - // Nothing to do - } - - /** - * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset, meaning that all - * bits that are set in the given std::bitset also have to be set in the underlyng std::bitset. Any additional bits - * that are set are not relevant. - * - * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. - * @return Whether the given flags are a subset or equivalent with the underlying std::bitset - */ - auto contains_flags(std::bitset<64U> other) const -> bool; - - /** - * @brief Allows to compare the underlying std::bitset of two instances - * - * @param other Other instance that we want to compare with - * @return Whether the underlying std::bitset of both types is the same - */ - auto operator==(elf_section_flags const & other) const -> bool = default; - - private: - std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 21 - 28 are reserved for operating - ///< system specific semantics and bits 29 - 32 are reserved for processor specific - ///< semantics. Bits 33 - 64 are unused for compatability with ELF32. - }; - - /** - * @brief Defines the data included in a section header, where each section has exactly one section header. - * See https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html for more information - */ - struct elf_section_header - { - uint32_t name_table_index; ///< Index into the section header string table, specifies the name of the section - elf_section_type type; ///< Categorizes the sections content and semantics - elf_section_flags flags; ///< 1-bit flgas that describe section attributes - uint64_t virtual_address; ///< If section appears in memory image of a process, gives address at which the sections - ///< first byte should reside, otherwise 0 - uint64_t file_offset; ///< Offset from the beginning of the file to the first byte in the section. SHT_NOBITS - ///< contains the conceptual placement instead (because it occupies no space in the file) - uint64_t section_size; ///< Complete section size in bytes, SHT_NOBITS may have non-zero value but will always - ///< occupy no space in the file - uint32_t other_section; ///< Section header table index link, behaviour varies on type - ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link - uint32_t additional_information; ///< Extra information, behaviour varies on type - ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link - uint64_t address_alignment; ///< Possible address alignment constraints. Value of virutal_address must be 0 % value - ///< of address_alignment. Value 0 or 1 mean no alignment constraints - uint64_t fixed_table_entry_size; ///< If sections holds table with fixed-sized entries, this gives the size in - ///< bytes of each entry - - /** - * @brief Detect whether a section header is inactive or not, should always be the case for the first entry in the - * sections table - * @return Whether the current section header is actually null or not, requires all fields besides section_size and - * other_section to contain 0 - */ - auto is_null() const -> bool; - }; - - /** - * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type - * multi_boot_tag_type::ELF_SECTIONS. - * The first section in the sections array will always be INACTIVE, there can only ever be one DYNAMIC section and - * only either one DYNAMIC_SYMBOL_TABLE or SYMBOL_TABLE. - */ - struct elf_symbols_section_header - { - tag info; ///< Basic multi_boot_tag information - uint32_t number_of_sections; ///< Number of sections in the sections array - uint32_t entry_size; ///< Size of each entry in the sections array - uint32_t section_index; ///< Index to the string table used for symbol names - std::byte end; ///< Marks the end of the tag, used to mark the beginning of any additional data - ///< contained in the section, to ensure byte alignment is actually 4 byte - }; -} // namespace teachos::arch::memory::multiboot - -#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp new file mode 100644 index 0000000..88d211e --- /dev/null +++ b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp @@ -0,0 +1,157 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP + +#include "info.hpp" +#include +#include + +namespace teachos::arch::memory::multiboot +{ + /** + * @brief Defines all elf section types an elf section header can have. See + * https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information. + */ + enum class elf_section_type : uint32_t + { + INACTIVE, ///< (SHT_NULL) Unused, meaning all values are zeroed out + PROGRAMM, ///< (SHT_PROGBITS) Program data (DATA, CODE) + SYMBOL_TABLE, ///< (SHT_SYMBTAB) Contains actual entries pointed to in symbol hash table + STRING_TABLE, ///< (SHT_STRTAB) Contains symbols, section and deubbging null-terminated strings + RELOCATION_ENTRY_WITH_ADDENDS, ///< (SHT_RELA) Only used on 64 bit systems + SYMBOL_HASH_TABLE, ///< (SHT_HASH) Hash table used by dynamic linker to locate symbols + DYNAMIC, ///< (SHT_DYNAMIC) Contains dynamic linking information + NOTE, ///< (SHT_NOTE) Stores information that marks files in some way + EMPTY, ///< (SHT_NOBITS) Program data section, that occupies no space in the file (.bss) + RELOCATION_ENTRY_WITHOUT_ADDENDS, ///< (SHT_REL) Only used on 32 bit systems + UNSPECIFIED, ///< (SHT_SHLIB) Reserved but has unspecified semantics + DYNAMIC_SYMBOL_TABLE, ///< (SHT_DYNSYM) Holds minimal set of symbols adequate for dynamic linking + INITALIZATION_FUNCTION_ARRAY = 14, ///< (SHT_INIT_ARRAY) Array of pointers to intialization functions () -> void + TERMINATION_FUNCTION_ARRAY, ///< (SHT_FINI_ARRAY) Array of pointers to termination functions () -> void + PRE_INITALIZATION_FUNCTION_ARRAY ///< (SHT_PRE_INIT_ARRAY) Array of pointers to functions invoked before other + ///< initalization functions () -> void + }; + + /** + * @brief Defines helper function for all states that the elf section flags of an elf section header can + * have. See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html + * See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information. + */ + struct elf_section_flags + { + /** + * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + */ + enum bitset : uint32_t + { + WRITABLE = 1U << 0U, ///< (SHF_WRITE) Section is writable at runtime. If it isn't then the section + ///< is assumed to be READONLY and only that flag is shown in the objdump. + OCCUPIES_MEMORY = 1U << 1U, ///< (SHF_ALLOC) Section occupies memory during execution. + ///< ALLOC flag is shown in the objdump. + EXECUTABLE_CODE = 1U << 2U, ///< (SHF_EXECINSTR) Section is executable. CODE flag is shown in the object dump. + DUPLICATE_DATA = 1U << 4U, ///< (SHF_MERGE) Section might be merged with another section. + CONTAINS_STRING = 1U << 5U, ///< (SHF_STRINGS) Section contains null-terminated strings. + SECTION_HEADER_INFO_IS_SECTION_HEADER_TABLE_INDEX = + 1U << 6U, ///< (SHF_INFO_LINK) Section contains the section header table index in the (sh_info) + ///< additional_information variable. + PRESERVE_ORDERING_AFTER_COMBINATION = + 1U << 7U, ///< (SHF_LINK_ORDER) Section preserves order after combining with another section. + REQUIRES_SPECIAL_OS_PROCESSING = + 1U << 8U, ///< (SHF_OS_NONCONFORMING) Section requires non-standard OS specific handling of its code or + ///< data, which does not confirm to standard ELF specifications. + SECTION_GROUP_MEMBER = 1U << 9U, ///< (SHF_GROUP) Section is a member of a section group. + HOLDS_THREAD_LOCAL_DATA = 1U << 10U, ///< (SHF_TLS) Section holds thread-local data. + COMPRESSED = 1U << 11U, ///< (SHF_COMPRESSED) Section contains compressed data. + SPECIAL_ORDERING_REQUIREMENTS = + 1U << 30U, ///< (SHF_ORDERED) Section has special ordering requirements, meaning it + ///< should be ordered in relation to other sections of the same type + EXCLUDED_UNLESS_REFERENCED_OR_ALLOCATED = 1U << 31U, ///< (SHF_EXCLUDE)Section is excluded unless referenced or + ///< allocated, used for LTO (Link-Time Optimizations) + }; + + /** + * @brief Constructor. + * + * @param flags Actual value read from the elf section header, which should be converted into a std::bitset, to + * allow reading the state of single bits more easily. + */ + explicit elf_section_flags(uint64_t flags) + : flags(flags) + { + // Nothing to do + } + + /** + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset, meaning that all + * bits that are set in the given std::bitset also have to be set in the underlyng std::bitset. Any additional bits + * that are set are not relevant. + * + * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. + * @return Whether the given flags are a subset or equivalent with the underlying std::bitset + */ + auto contains_flags(std::bitset<64U> other) const -> bool; + + /** + * @brief Allows to compare the underlying std::bitset of two instances + * + * @param other Other instance that we want to compare with + * @return Whether the underlying std::bitset of both types is the same + */ + auto operator==(elf_section_flags const & other) const -> bool = default; + + private: + std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 21 - 28 are reserved for operating + ///< system specific semantics and bits 29 - 32 are reserved for processor specific + ///< semantics. Bits 33 - 64 are unused for compatability with ELF32. + }; + + /** + * @brief Defines the data included in a section header, where each section has exactly one section header. + * See https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html for more information + */ + struct elf_section_header + { + uint32_t name_table_index; ///< Index into the section header string table, specifies the name of the section + elf_section_type type; ///< Categorizes the sections content and semantics + elf_section_flags flags; ///< 1-bit flgas that describe section attributes + uint64_t virtual_address; ///< If section appears in memory image of a process, gives address at which the sections + ///< first byte should reside, otherwise 0 + uint64_t file_offset; ///< Offset from the beginning of the file to the first byte in the section. SHT_NOBITS + ///< contains the conceptual placement instead (because it occupies no space in the file) + uint64_t section_size; ///< Complete section size in bytes, SHT_NOBITS may have non-zero value but will always + ///< occupy no space in the file + uint32_t other_section; ///< Section header table index link, behaviour varies on type + ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link + uint32_t additional_information; ///< Extra information, behaviour varies on type + ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link + uint64_t address_alignment; ///< Possible address alignment constraints. Value of virutal_address must be 0 % value + ///< of address_alignment. Value 0 or 1 mean no alignment constraints + uint64_t fixed_table_entry_size; ///< If sections holds table with fixed-sized entries, this gives the size in + ///< bytes of each entry + + /** + * @brief Detect whether a section header is inactive or not, should always be the case for the first entry in the + * sections table + * @return Whether the current section header is actually null or not, requires all fields besides section_size and + * other_section to contain 0 + */ + auto is_null() const -> bool; + }; + + /** + * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type + * multi_boot_tag_type::ELF_SECTIONS. + * The first section in the sections array will always be INACTIVE, there can only ever be one DYNAMIC section and + * only either one DYNAMIC_SYMBOL_TABLE or SYMBOL_TABLE. + */ + struct elf_symbols_section_header + { + tag info; ///< Basic multi_boot_tag information + uint32_t number_of_sections; ///< Number of sections in the sections array + uint32_t entry_size; ///< Size of each entry in the sections array + uint32_t section_index; ///< Index to the string table used for symbol names + std::byte end; ///< Marks the end of the tag, used to mark the beginning of any additional data + ///< contained in the section, to ensure byte alignment is actually 4 byte + }; +} // namespace teachos::arch::memory::multiboot + +#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/reader.hpp b/arch/x86_64/include/arch/memory/multiboot/reader.hpp index 14086a7..2f72980 100644 --- a/arch/x86_64/include/arch/memory/multiboot/reader.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/reader.hpp @@ -1,7 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP #define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP -#include "elf_sybols_section.hpp" +#include "elf_symbols_section.hpp" #include "memory_map.hpp" #include diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 32e49e5..da63d8c 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -48,9 +48,9 @@ namespace teachos::arch::memory::paging auto zero_entries() -> void; /** - * @brief Gets the complete next page table level from the given page table index. Meaning we use an index into a - * Level 4 page table to get the according Level 3 page table. When using this on an a level 1 page table it will - * cause an assertion. + * @brief Turn this page table into the next page table level from the given page table index. Meaning we + * use an index into a Level 4 page table to get the according Level 3 page table. When using this on an a level 1 + * page table it will cause an assertion. * * @param table_index Index of this page table in the page table one level higher. */ -- cgit v1.2.3 From 7ebfe9e09efa84044d1470132b7f55ebf53a7f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 06:32:02 +0000 Subject: Fix next_table_address --- arch/x86_64/include/arch/memory/paging/page_table.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index da63d8c..73b75ad 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -89,7 +89,7 @@ namespace teachos::arch::memory::paging * @param table_index Index of this page table in the page table one level higher. * @return An optional of the address of the next page table or null. */ - auto next_table_address(std::size_t table_index) const -> std::optional; + auto next_table_address(std::size_t table_index) -> std::optional; level current_level; ///< Current level of the page table, used to ensure next_table() is never called with a level ///< 1 page table -- cgit v1.2.3 From d728052d62470799f73f6d9a2b8baa2b0b357383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 07:01:53 +0000 Subject: Add helper methods to phyisca frame --- .../arch/memory/allocator/physical_frame.hpp | 12 ++++++----- .../include/arch/memory/paging/virtual_page.hpp | 25 +++++++++++++++++++++- 2 files changed, 31 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp index 5e99d10..e013e0d 100644 --- a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp +++ b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp @@ -6,6 +6,8 @@ namespace teachos::arch::memory::allocator { + constexpr std::size_t 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. @@ -15,22 +17,22 @@ namespace teachos::arch::memory::allocator /** * @brief Constructor. * - * @param frame_number Index number that should be assigned to this physical_frame. + * @param frame_number Index number that should be assigned to this physical frame. */ explicit physical_frame(std::size_t frame_number); /** - * @brief Returns the physical_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 physical_frame for. + * @param physical_address Physical 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) -> physical_frame; + static auto containing_address(std::size_t physical_address) -> physical_frame; /** * @brief Evaluates the start address of the physical frame. * - * @return start address of the physical frame. + * @return Start address of the physical frame. */ auto start_address() const -> uint64_t; diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index 12af510..7871e4b 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -2,6 +2,7 @@ #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP #include +#include namespace teachos::arch::memory::paging { @@ -10,7 +11,27 @@ namespace teachos::arch::memory::paging */ struct virtual_page { - std::size_t number; ///< Index number of the current virtual page, used to distinguish it from other pages. + /** + * @brief Constructor. + * + * @param page_number Index number of the current virtual page, used to distinguish it from other pages. + */ + explicit virtual_page(std::size_t page_number); + + /** + * @brief Returns the virtual page the given address is contained in. + * + * @param virtual_address Virtual address we want to get the corresponding virtual page for. + * @return Frame the given address is contained in. + */ + static auto containing_address(std::size_t virtual_address) -> virtual_page; + + /** + * @brief Evaluates the start address of the virtual page. + * + * @return Start address of the virtual page. + */ + auto start_address() const -> uint64_t; /** * @brief Defaulted equals operator. @@ -21,6 +42,8 @@ namespace teachos::arch::memory::paging * @brief Defaulted three-way comparsion operator. */ constexpr auto operator<=>(const virtual_page & other) const -> std::partial_ordering = default; + + std::size_t page_number; ///< Index number of the current virtual page, used to distinguish it from other pages. }; } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From e5206b3bf1883fd9601a37f5cce392d8080b8791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 07:43:00 +0000 Subject: Add get level index method to virtual page --- arch/x86_64/include/arch/memory/paging/page_entry.hpp | 2 +- arch/x86_64/include/arch/memory/paging/page_table.hpp | 10 +--------- arch/x86_64/include/arch/memory/paging/virtual_page.hpp | 11 ++++++++++- 3 files changed, 12 insertions(+), 11 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index a40e764..016e054 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -87,4 +87,4 @@ namespace teachos::arch::memory::paging }; } // namespace teachos::arch::memory::paging -#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_ENTRY_HPP \ No newline at end of file +#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_ENTRY_HPP diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 73b75ad..bbee477 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -73,14 +73,6 @@ namespace teachos::arch::memory::paging auto operator[](std::size_t index) const -> entry const &; private: - /** - * @brief Constructor. Used internally to create new page tables. - * - * @param new_level New level of the page table. - * @param new_table New table data contained in the page table. - */ - page_table(level new_level, table_content * new_table); - /** * @brief Calculates the address of the next page table level for the given table index. The next page table address * is only valid if the corresponding entry is present and not a huge page. Meaning we use an index into a @@ -97,4 +89,4 @@ namespace teachos::arch::memory::paging }; } // namespace teachos::arch::memory::paging -#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP \ No newline at end of file +#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index 7871e4b..a2e5316 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -1,6 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP +#include "page_table.hpp" #include #include @@ -33,6 +34,14 @@ namespace teachos::arch::memory::paging */ auto start_address() const -> uint64_t; + /** + * @brief Calculates the index into the page table with the given level, which leads to this virtual page. + * + * @param level Level of the page table we want to calculate the index for. + * @return Index into the page table with the given level. + */ + auto get_level_index(page_table::level level) const -> uint64_t; + /** * @brief Defaulted equals operator. */ @@ -47,4 +56,4 @@ namespace teachos::arch::memory::paging }; } // namespace teachos::arch::memory::paging -#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP \ No newline at end of file +#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP -- cgit v1.2.3 From f8928c877c48b5beba9bb42876f70213aba68f88 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 07:46:51 +0000 Subject: translate --- .../include/arch/memory/paging/virtual_page.hpp | 63 +++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index a2e5316..b2adca3 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -1,12 +1,73 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP -#include "page_table.hpp" +#include "arch/memory/allocator/physical_frame.hpp" +#include "arch/memory/paging/page_table.hpp" + #include #include +#include namespace teachos::arch::memory::paging { + /** + * @brief Translate virtual into phyical address + * + * @param virtual_address Address to translate into physical + * @return Physical address + */ + auto static translate_address(std::size_t virtual_address) -> std::optional + { + std::size_t offset = virtual_address % allocator::PAGE_FRAME_SIZE; + virtual_page page = virtual_page::containing_address(virtual_address); + allocator::physical_frame frame = paging::translate_page(page); + + if (frame.value()) + { + return frame->number * allocator::PAGE_FRAME_SIZE + offset; + } + + return std::nullopt; + } + + /** + * @brief Translate page into physical_frame + * + * @param page Page to translate into physical_frame + * @return Physical frame corresponding to the provided page_table + */ + auto static translate_page(virtual_page page) -> std::optional + { + auto level3 = + reinterpret_cast(page_table::LEVEL4)->next_table(page.get_level_index(page_table::LEVEL4)); + + auto huge_page = []() { + // TODO + }; + + if (level3.value()) + { + auto level2 = level3->next_table(page.get_level_index(page_table::LEVEL3)); + + if (level2.value()) + { + auto level1 = level2->next_table(page.get_level_index(page_table::LEVEL2)); + + if (level1.value()) + { + auto frame = level1[page.get_level_index(page_table::LEVEL1)].calculate_pointed_to_frame(); + + if (frame.value()) + { + return frame; + } + } + } + } + + return huge_page(); + } + /** * @brief Virtual page entry contained in P1 page tables */ -- cgit v1.2.3 From 882ccdcc0e3c19fbcc595c6a371ef79587f63648 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 08:11:19 +0000 Subject: implement translate_page --- .../include/arch/memory/paging/page_table.hpp | 2 +- .../include/arch/memory/paging/virtual_page.hpp | 121 +++++++++++---------- 2 files changed, 63 insertions(+), 60 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index bbee477..aa8bd5e 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -54,7 +54,7 @@ namespace teachos::arch::memory::paging * * @param table_index Index of this page table in the page table one level higher. */ - auto next_table(std::size_t table_index) -> void; + auto next_table(std::size_t table_index) -> bool; /** * @brief Index operator overload to access specific mutable entry directy. diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index b2adca3..5a025fa 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -2,72 +2,14 @@ #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP #include "arch/memory/allocator/physical_frame.hpp" -#include "arch/memory/paging/page_table.hpp" +#include "page_table.hpp" #include #include #include namespace teachos::arch::memory::paging { - /** - * @brief Translate virtual into phyical address - * - * @param virtual_address Address to translate into physical - * @return Physical address - */ - auto static translate_address(std::size_t virtual_address) -> std::optional - { - std::size_t offset = virtual_address % allocator::PAGE_FRAME_SIZE; - virtual_page page = virtual_page::containing_address(virtual_address); - allocator::physical_frame frame = paging::translate_page(page); - - if (frame.value()) - { - return frame->number * allocator::PAGE_FRAME_SIZE + offset; - } - - return std::nullopt; - } - - /** - * @brief Translate page into physical_frame - * - * @param page Page to translate into physical_frame - * @return Physical frame corresponding to the provided page_table - */ - auto static translate_page(virtual_page page) -> std::optional - { - auto level3 = - reinterpret_cast(page_table::LEVEL4)->next_table(page.get_level_index(page_table::LEVEL4)); - - auto huge_page = []() { - // TODO - }; - - if (level3.value()) - { - auto level2 = level3->next_table(page.get_level_index(page_table::LEVEL3)); - - if (level2.value()) - { - auto level1 = level2->next_table(page.get_level_index(page_table::LEVEL2)); - - if (level1.value()) - { - auto frame = level1[page.get_level_index(page_table::LEVEL1)].calculate_pointed_to_frame(); - - if (frame.value()) - { - return frame; - } - } - } - } - - return huge_page(); - } - /** * @brief Virtual page entry contained in P1 page tables */ @@ -115,6 +57,67 @@ namespace teachos::arch::memory::paging std::size_t page_number; ///< Index number of the current virtual page, used to distinguish it from other pages. }; + + /** + * @brief Translate page into physical_frame + * + * @param page Page to translate into physical_frame + * @return Physical frame corresponding to the provided page_table + */ + auto translate_page(virtual_page page) -> std::optional + { + page_table page_table{}; + bool is_valid = page_table.next_table(page.get_level_index(page_table::LEVEL4)); + + auto huge_page = []() -> std::optional { + // TODO + return std::nullopt; + }; + + if (is_valid) + { + is_valid = page_table.next_table(page.get_level_index(page_table::LEVEL3)); + + if (is_valid) + { + is_valid = page_table.next_table(page.get_level_index(page_table::LEVEL2)); + + if (is_valid) + { + auto level1_index = page.get_level_index(page_table::LEVEL1); + auto frame = page_table[level1_index].calculate_pointed_to_frame(); + + if (frame.has_value()) + { + return frame; + } + } + } + } + + return huge_page(); + } + + /** + * @brief Translate virtual into phyical address + * + * @param virtual_address Address to translate into physical + * @return Physical address + */ + auto translate_address(std::size_t virtual_address) -> std::optional + { + std::size_t offset = virtual_address % allocator::PAGE_FRAME_SIZE; + virtual_page page = virtual_page::containing_address(virtual_address); + std::optional frame = translate_page(page); + + if (frame.has_value()) + { + return frame.value().frame_number * allocator::PAGE_FRAME_SIZE + offset; + } + + return std::nullopt; + } + } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP -- cgit v1.2.3 From 5b5e8dec97f6f619faa13ee813df21837fe83a57 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 08:13:33 +0000 Subject: add types --- arch/x86_64/include/arch/memory/paging/virtual_page.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index 5a025fa..1ba0f7c 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -84,8 +84,8 @@ namespace teachos::arch::memory::paging if (is_valid) { - auto level1_index = page.get_level_index(page_table::LEVEL1); - auto frame = page_table[level1_index].calculate_pointed_to_frame(); + std::size_t level1_index = page.get_level_index(page_table::LEVEL1); + std::optional frame = page_table[level1_index].calculate_pointed_to_frame(); if (frame.has_value()) { -- cgit v1.2.3 From fba2fc4ce3d4bf4997eb42c9b5b2ac1de8692150 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 08:14:54 +0000 Subject: remove faulty if statement --- arch/x86_64/include/arch/memory/paging/virtual_page.hpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index 1ba0f7c..46140ff 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -87,10 +87,7 @@ namespace teachos::arch::memory::paging std::size_t level1_index = page.get_level_index(page_table::LEVEL1); std::optional frame = page_table[level1_index].calculate_pointed_to_frame(); - if (frame.has_value()) - { - return frame; - } + return frame; } } } -- cgit v1.2.3 From d934ea6875932a7139eba77bb5248fca8be7fd01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 08:37:49 +0000 Subject: =?UTF-8?q?Implement=20translate=20page=20in=20a=20big=20brain=20w?= =?UTF-8?q?ay=20=F0=9F=A4=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../include/arch/memory/paging/page_table.hpp | 2 ++ .../include/arch/memory/paging/virtual_page.hpp | 32 +++++++++------------- 2 files changed, 15 insertions(+), 19 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index aa8bd5e..0fe667c 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -87,6 +87,8 @@ namespace teachos::arch::memory::paging ///< 1 page table table_content * current_table; ///< Current table we are accessing and indexing. }; + + auto operator--(page_table::level & level, int) -> page_table::level; } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index 46140ff..705de29 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -67,31 +67,25 @@ namespace teachos::arch::memory::paging auto translate_page(virtual_page page) -> std::optional { page_table page_table{}; - bool is_valid = page_table.next_table(page.get_level_index(page_table::LEVEL4)); + bool is_valid = false; + auto huge_page = []() -> std::optional { return std::nullopt; }; - auto huge_page = []() -> std::optional { - // TODO - return std::nullopt; - }; - - if (is_valid) + for (auto level = page_table::LEVEL4; level != page_table::LEVEL1; level--) { - is_valid = page_table.next_table(page.get_level_index(page_table::LEVEL3)); - - if (is_valid) + is_valid = page_table.next_table(page.get_level_index(level)); + if (!is_valid) { - is_valid = page_table.next_table(page.get_level_index(page_table::LEVEL2)); - - if (is_valid) - { - std::size_t level1_index = page.get_level_index(page_table::LEVEL1); - std::optional frame = page_table[level1_index].calculate_pointed_to_frame(); - - return frame; - } + break; } } + if (is_valid) + { + auto level1_index = page.get_level_index(page_table::LEVEL1); + auto frame = page_table[level1_index].calculate_pointed_to_frame(); + return frame; + } + return huge_page(); } -- cgit v1.2.3 From 1d157101eb550f99dac9ec943053f85bbf6c7644 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 09:03:30 +0000 Subject: create page_mapper --- .../include/arch/memory/paging/page_mapper.hpp | 30 +++++++++++++ .../include/arch/memory/paging/virtual_page.hpp | 51 ---------------------- 2 files changed, 30 insertions(+), 51 deletions(-) create mode 100644 arch/x86_64/include/arch/memory/paging/page_mapper.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp new file mode 100644 index 0000000..b151a7f --- /dev/null +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -0,0 +1,30 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP + +#include "arch/memory/paging/virtual_page.hpp" + +#include + +namespace teachos::arch::memory::paging +{ + /** + * @brief Translate page into physical_frame + * + * @param page Page to translate into physical_frame + * @return Physical frame corresponding to the provided page_table + */ + auto translate_page(virtual_page page) -> std::optional; + + /** + * @brief Translate virtual into phyical address + * + * @param virtual_address Address to translate into physical + * @return Physical address + */ + auto translate_address(std::size_t virtual_address) -> std::optional; + + auto map_page_to_frame(memory::allocator::area_frame_allocator & allocator, const Page & page, const Frame & frame, + EntryFlags flags) -> void; +} // namespace teachos::arch::memory::paging + +#endif \ No newline at end of file diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index 705de29..6b9a641 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -58,57 +58,6 @@ namespace teachos::arch::memory::paging std::size_t page_number; ///< Index number of the current virtual page, used to distinguish it from other pages. }; - /** - * @brief Translate page into physical_frame - * - * @param page Page to translate into physical_frame - * @return Physical frame corresponding to the provided page_table - */ - auto translate_page(virtual_page page) -> std::optional - { - page_table page_table{}; - bool is_valid = false; - auto huge_page = []() -> std::optional { return std::nullopt; }; - - for (auto level = page_table::LEVEL4; level != page_table::LEVEL1; level--) - { - is_valid = page_table.next_table(page.get_level_index(level)); - if (!is_valid) - { - break; - } - } - - if (is_valid) - { - auto level1_index = page.get_level_index(page_table::LEVEL1); - auto frame = page_table[level1_index].calculate_pointed_to_frame(); - return frame; - } - - return huge_page(); - } - - /** - * @brief Translate virtual into phyical address - * - * @param virtual_address Address to translate into physical - * @return Physical address - */ - auto translate_address(std::size_t virtual_address) -> std::optional - { - std::size_t offset = virtual_address % allocator::PAGE_FRAME_SIZE; - virtual_page page = virtual_page::containing_address(virtual_address); - std::optional frame = translate_page(page); - - if (frame.has_value()) - { - return frame.value().frame_number * allocator::PAGE_FRAME_SIZE + offset; - } - - return std::nullopt; - } - } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP -- cgit v1.2.3 From 04bd6a059b9eb105024044d74122b0cb76cebf14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 09:34:03 +0000 Subject: Add translate huge page method --- .../include/arch/memory/paging/page_mapper.hpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index b151a7f..ad9db52 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -8,18 +8,27 @@ namespace teachos::arch::memory::paging { /** - * @brief Translate page into physical_frame + * @brief Translates page into physical frame, will first attempt to parse normally using default page size and if it + * failed attempt to parse using huge pages. * - * @param page Page to translate into physical_frame - * @return Physical frame corresponding to the provided page_table + * @param page Page to translate into physical frame. + * @return Physical frame corresponding to the provided virtual page. */ auto translate_page(virtual_page page) -> std::optional; /** - * @brief Translate virtual into phyical address + * @brief Translates huge page into actual physical frame. * - * @param virtual_address Address to translate into physical - * @return Physical address + * @param page Page to translate into physical frame. + * @return Physical frame corresponding to the provided virtual page. + */ + auto translate_huge_page(virtual_page page) -> std::optional; + + /** + * @brief Translate virtual into phyical address. + * + * @param virtual_address Address to translate into physical. + * @return Physical address. */ auto translate_address(std::size_t virtual_address) -> std::optional; -- cgit v1.2.3 From ecf89844100248db3ad08d5c76091de563488b95 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 09:37:08 +0000 Subject: implement map_page_to_frame --- arch/x86_64/include/arch/memory/paging/page_entry.hpp | 2 +- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index 016e054..8dd061f 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -60,7 +60,7 @@ namespace teachos::arch::memory::paging * * @param frame Physical frame that contains the address we want to copy into our underlying std::bitset. */ - auto set_address(allocator::physical_frame frame) -> void; + auto entry::set_entry(allocator::physical_frame frame, std::bitset<64U> additional_flags) -> void; /** * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset, meaning that all diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index ad9db52..5960aaf 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -1,6 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP +#include "arch/memory/allocator/area_frame_allocator.hpp" #include "arch/memory/paging/virtual_page.hpp" #include @@ -32,8 +33,16 @@ namespace teachos::arch::memory::paging */ auto translate_address(std::size_t virtual_address) -> std::optional; - auto map_page_to_frame(memory::allocator::area_frame_allocator & allocator, const Page & page, const Frame & frame, - EntryFlags flags) -> void; + /** + * @brief TODO + * + * @param allocator + * @param page + * @param frame + * @param flags + */ + auto map_page_to_frame(memory::allocator::area_frame_allocator & allocator, const virtual_page & page, + const memory::allocator::physical_frame & frame, entry::bitset flags) -> void; } // namespace teachos::arch::memory::paging #endif \ No newline at end of file -- cgit v1.2.3 From f47f1468c8c281ee9603b7669f5e685e5f36fa3f Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 11:23:02 +0000 Subject: finalize map_page_to_frame --- arch/x86_64/include/arch/memory/paging/page_entry.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index 8dd061f..109735d 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -60,7 +60,7 @@ namespace teachos::arch::memory::paging * * @param frame Physical frame that contains the address we want to copy into our underlying std::bitset. */ - auto entry::set_entry(allocator::physical_frame frame, std::bitset<64U> additional_flags) -> void; + auto set_entry(allocator::physical_frame frame, std::bitset<64U> additional_flags) -> void; /** * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset, meaning that all -- cgit v1.2.3 From f4a14572a661b1f2bac283615d5b070408b382f7 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 11:24:58 +0000 Subject: fix syntax --- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 5960aaf..c82b08c 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -41,8 +41,8 @@ namespace teachos::arch::memory::paging * @param frame * @param flags */ - auto map_page_to_frame(memory::allocator::area_frame_allocator & allocator, const virtual_page & page, - const memory::allocator::physical_frame & frame, entry::bitset flags) -> void; + auto map_page_to_frame(memory::allocator::area_frame_allocator & allocator, virtual_page const & page, + memory::allocator::physical_frame const & frame, entry::bitset flags) -> void; } // namespace teachos::arch::memory::paging #endif \ No newline at end of file -- cgit v1.2.3 From da2341ec12128d3b4983a67d39aeaf76b1781fa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 12:02:20 +0000 Subject: Add printf like behaviour to assert --- .../include/arch/exception_handling/assert.hpp | 52 +++++++++++++++++++--- 1 file changed, 46 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/exception_handling/assert.hpp b/arch/x86_64/include/arch/exception_handling/assert.hpp index f355a61..152e653 100644 --- a/arch/x86_64/include/arch/exception_handling/assert.hpp +++ b/arch/x86_64/include/arch/exception_handling/assert.hpp @@ -1,16 +1,56 @@ #ifndef TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_ASSERT_HPP #define TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_ASSERT_HPP +#include "arch/exception_handling/panic.hpp" + +#include + namespace teachos::arch::exception_handling { + namespace + { + char constexpr FAILED_MESSAGE[] = "Invalid arguments passed to format specifiers (%) in exception_handling::assert"; + } + /** - * @brief assert a condition to be true, if not do not continue - * execution of the code and print message to screen + * @brief Assert a condition to be true, if not do not continue + * execution of the code and print the formatted message to screen. * - * @param condition - * @param message + * @param condition Condition we want to be true. + * @param format Formatting message that the given arguments will be inserted into. + * @param ...args Arguments that will be formatted and inserted into the resulting string, replacing their respective + * specifiers. Uses the printf specifiers see https://cplusplus.com/reference/cstdio/printf/ for more information. */ - auto assert(bool condition, char const * message) -> void; + template + auto assert(bool condition, char const * format, Args const &... args) -> void + { + if (condition) + { + return; + } + else if constexpr (sizeof...(args) == 0) + { + panic("Assertion Violation: ", format); + } + + // Result is what would have been written if the passed buffer would have been large enough not counting null + // character, or if an error occured while creating the string a negative number is returned instead. To ensure this + // will not crash the system when creating an array with negative size we assert beforehand with a clear error + // message. + int const size = snprintf(nullptr, 0U, format, args...) + 1U; + if (size < 0) + { + panic("Assertion Violation: ", FAILED_MESSAGE); + } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wvla" + char arguments[size] = {}; +#pragma GCC diagnostic pop + int const written_characters = snprintf(arguments, size, format, args...); + // Written characters is expected to be one less, because of the null termination character. + bool const result = (written_characters == (size - 1)); + panic("Assertion Violation: ", result ? arguments : FAILED_MESSAGE); + } } // namespace teachos::arch::exception_handling -#endif \ No newline at end of file +#endif -- cgit v1.2.3 From 2129bdb22bab7dc5a9d23a31c23f38e847511a46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 12:17:44 +0000 Subject: =?UTF-8?q?Revert=20assert=20with=20printf=20functionality,=20requ?= =?UTF-8?q?ires=20malloc=20=F0=9F=98=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../include/arch/exception_handling/assert.hpp | 44 ++-------------------- 1 file changed, 3 insertions(+), 41 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/exception_handling/assert.hpp b/arch/x86_64/include/arch/exception_handling/assert.hpp index 152e653..bfc205c 100644 --- a/arch/x86_64/include/arch/exception_handling/assert.hpp +++ b/arch/x86_64/include/arch/exception_handling/assert.hpp @@ -3,54 +3,16 @@ #include "arch/exception_handling/panic.hpp" -#include - namespace teachos::arch::exception_handling { - namespace - { - char constexpr FAILED_MESSAGE[] = "Invalid arguments passed to format specifiers (%) in exception_handling::assert"; - } - /** * @brief Assert a condition to be true, if not do not continue * execution of the code and print the formatted message to screen. * - * @param condition Condition we want to be true. - * @param format Formatting message that the given arguments will be inserted into. - * @param ...args Arguments that will be formatted and inserted into the resulting string, replacing their respective - * specifiers. Uses the printf specifiers see https://cplusplus.com/reference/cstdio/printf/ for more information. + * @param condition Condition we want to be true or else halt execution. + * @param message Message that should be printed before halting the execution if the condition is not met. */ - template - auto assert(bool condition, char const * format, Args const &... args) -> void - { - if (condition) - { - return; - } - else if constexpr (sizeof...(args) == 0) - { - panic("Assertion Violation: ", format); - } - - // Result is what would have been written if the passed buffer would have been large enough not counting null - // character, or if an error occured while creating the string a negative number is returned instead. To ensure this - // will not crash the system when creating an array with negative size we assert beforehand with a clear error - // message. - int const size = snprintf(nullptr, 0U, format, args...) + 1U; - if (size < 0) - { - panic("Assertion Violation: ", FAILED_MESSAGE); - } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wvla" - char arguments[size] = {}; -#pragma GCC diagnostic pop - int const written_characters = snprintf(arguments, size, format, args...); - // Written characters is expected to be one less, because of the null termination character. - bool const result = (written_characters == (size - 1)); - panic("Assertion Violation: ", result ? arguments : FAILED_MESSAGE); - } + auto assert(bool condition, char const * message) -> void; } // namespace teachos::arch::exception_handling #endif -- cgit v1.2.3 From aa0634589cb7d51f57e3e555bb15ebca99bc162e Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 12:17:58 +0000 Subject: document page mapping and entry --- arch/x86_64/include/arch/memory/paging/page_entry.hpp | 3 ++- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 12 +++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index 109735d..2d97d77 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -59,8 +59,9 @@ namespace teachos::arch::memory::paging * calculate_physical_address() will return the new address instead of the old one. * * @param frame Physical frame that contains the address we want to copy into our underlying std::bitset. + * @param flags Entry flags which will be set on the entry */ - auto set_entry(allocator::physical_frame frame, std::bitset<64U> additional_flags) -> void; + auto set_entry(allocator::physical_frame frame, std::bitset<64U> flags) -> void; /** * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset, meaning that all diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index c82b08c..069161f 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -34,13 +34,15 @@ namespace teachos::arch::memory::paging auto translate_address(std::size_t virtual_address) -> std::optional; /** - * @brief TODO + * @brief Maps a virtual page to a physical frame in the page table with the specified flags. * - * @param allocator - * @param page - * @param frame - * @param flags + * @param allocator Reference to the area frame allocator, which is used to allocate frames when a new page table is + * required. + * @param page Reference to the virtual page that is being mapped. + * @param frame The physical frame that the virtual page will be mapped to. + * @param flags A bitset of flags that configure the page table entry for this mapping. */ + auto map_page_to_frame(memory::allocator::area_frame_allocator & allocator, virtual_page const & page, memory::allocator::physical_frame const & frame, entry::bitset flags) -> void; } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 8e9a924f9fba18de9a5e37b1baf1d97e9b008251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 12:21:57 +0000 Subject: Fix useless copy by reference --- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 069161f..699d517 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -42,9 +42,8 @@ namespace teachos::arch::memory::paging * @param frame The physical frame that the virtual page will be mapped to. * @param flags A bitset of flags that configure the page table entry for this mapping. */ - - auto map_page_to_frame(memory::allocator::area_frame_allocator & allocator, virtual_page const & page, - memory::allocator::physical_frame const & frame, entry::bitset flags) -> void; + auto map_page_to_frame(allocator::area_frame_allocator & allocator, virtual_page page, + allocator::physical_frame frame, entry::bitset flags) -> void; } // namespace teachos::arch::memory::paging -#endif \ No newline at end of file +#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP -- cgit v1.2.3 From dd5dab7fd34c6745a16ac572ecd099e4bc26c1fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 12:35:39 +0000 Subject: Fix set_entry flags usage --- arch/x86_64/include/arch/memory/paging/page_entry.hpp | 6 +++--- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index 2d97d77..158af2e 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -55,11 +55,11 @@ namespace teachos::arch::memory::paging auto calculate_pointed_to_frame() const -> std::optional; /** - * @brief Copies the address from the given physical frame into the underlying std::bitset so future calls to - * calculate_physical_address() will return the new address instead of the old one. + * @brief Copies the address and flags from the given physical frame into the underlying std::bitset so future calls + * to calculate_physical_address() will return the new address and flags instead of the old one. * * @param frame Physical frame that contains the address we want to copy into our underlying std::bitset. - * @param flags Entry flags which will be set on the entry + * @param flags Entry flags which will be copied into our underlying std::bitset. */ auto set_entry(allocator::physical_frame frame, std::bitset<64U> flags) -> void; diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 699d517..635a848 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -43,7 +43,7 @@ namespace teachos::arch::memory::paging * @param flags A bitset of flags that configure the page table entry for this mapping. */ auto map_page_to_frame(allocator::area_frame_allocator & allocator, virtual_page page, - allocator::physical_frame frame, entry::bitset flags) -> void; + allocator::physical_frame frame, std::bitset<64U> flags) -> void; } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP -- cgit v1.2.3 From bb8b3f9c0734220702e3e930e7acb4906aa13db6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 12:48:51 +0000 Subject: Make map_page_to_frame use concept --- .../arch/memory/allocator/area_frame_allocator.hpp | 6 +++ .../include/arch/memory/paging/page_mapper.hpp | 43 ++++++++++++++++++---- 2 files changed, 42 insertions(+), 7 deletions(-) (limited to 'arch/x86_64/include') 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 c9d4e7f..f99b7c8 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 @@ -8,6 +8,12 @@ namespace teachos::arch::memory::allocator { + template + concept FrameAllocator = requires(T t) { + { t.allocate_frame() } -> std::same_as>; + { t.deallocate_frame() } -> std::same_as; + }; + /** * @brief Allocates memory using memory areas read from the multiboot2 information pointer. */ diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 635a848..5bdd82a 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -1,6 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP +#include "arch/exception_handling/assert.hpp" #include "arch/memory/allocator/area_frame_allocator.hpp" #include "arch/memory/paging/virtual_page.hpp" @@ -34,16 +35,44 @@ namespace teachos::arch::memory::paging auto translate_address(std::size_t virtual_address) -> std::optional; /** - * @brief Maps a virtual page to a physical frame in the page table with the specified flags. + * @brief Maps a virtual page to a physical frame in the page table with the specified flags. Allocates and maps an + * entry in every page level if it does not exists yet down to level 1. If the level 1 page table already exists it + * halts execution instead. * - * @param allocator Reference to the area frame allocator, which is used to allocate frames when a new page table is - * required. - * @param page Reference to the virtual page that is being mapped. - * @param frame The physical frame that the virtual page will be mapped to. + * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate entries + * when a new page table is required. + * @param page Virtual page that is being mapped. + * @param frame Physical frame that the virtual page will be mapped to. * @param flags A bitset of flags that configure the page table entry for this mapping. */ - auto map_page_to_frame(allocator::area_frame_allocator & allocator, virtual_page page, - allocator::physical_frame frame, std::bitset<64U> flags) -> void; + template + auto map_page_to_frame(T & allocator, virtual_page page, allocator::physical_frame frame, + std::bitset<64U> flags) -> void + + { + page_table page_table{}; + bool table_exists = false; + + for (auto level = page_table::LEVEL4; level != page_table::LEVEL1; level--) + { + std::size_t level_index = page.get_level_index(level); + table_exists = page_table.next_table(level_index); + + if (!table_exists) + { + auto allocated_frame = allocator.allocate_frame(); + exception_handling::assert(!allocated_frame.has_value(), "[Page mapper]: Unable to allocate frame"); + page_table[level_index].set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); + page_table.zero_entries(); + } + } + + auto level1_entry = page_table[page.get_level_index(page_table::LEVEL1)]; + arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE), + "[Page Mapper]: Unable to map huge pages"); + arch::exception_handling::assert(!level1_entry.is_unused(), "[Page Mapper]: Page table entry is already used"); + level1_entry.set_entry(frame, flags | std::bitset<64U>{entry::PRESENT}); + } } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP -- cgit v1.2.3 From 1b03bcecac1276b486e17daf0384de7fa203d974 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 20 Oct 2024 12:57:21 +0000 Subject: create active_page_table --- .../arch/memory/paging/active_page_table.hpp | 31 ++++++++++++++++++++++ .../include/arch/memory/paging/page_mapper.hpp | 1 - 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 arch/x86_64/include/arch/memory/paging/active_page_table.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp new file mode 100644 index 0000000..4a94b40 --- /dev/null +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -0,0 +1,31 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP + +#include "arch/memory/paging/page_table.hpp" + +namespace teachos::arch::memory::paging +{ + + struct active_page_table + { + /** + * @brief Ensures only one instance of active_page_table exists. + * + * @param level4_page_table A pointer to the level 4 page table. + * @return The only instance of active_page_table. + */ + auto create(page_table * level4_page_table) -> active_page_table *; + + private: + /** + * @brief Construct a new active page table object. + * + * @param level4_page_table A pointer to the level 4 page table. + */ + active_page_table(page_table * level4_page_table); + + bool instantiated = false; ///< Indicates wether an instance already exists. + page_table * level4_page_table; ///< The active level4 page table. + }; +} // namespace teachos::arch::memory::paging +#endif \ No newline at end of file diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 5bdd82a..ae3502e 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -48,7 +48,6 @@ namespace teachos::arch::memory::paging template auto map_page_to_frame(T & allocator, virtual_page page, allocator::physical_frame frame, std::bitset<64U> flags) -> void - { page_table page_table{}; bool table_exists = false; -- cgit v1.2.3 From 49ae81912f3a440f1958e86296d468ec669f71a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 20 Oct 2024 13:17:24 +0000 Subject: Fix active page table cpp --- arch/x86_64/include/arch/memory/paging/active_page_table.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index 4a94b40..3933d5a 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -28,4 +28,5 @@ namespace teachos::arch::memory::paging page_table * level4_page_table; ///< The active level4 page table. }; } // namespace teachos::arch::memory::paging -#endif \ No newline at end of file + +#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP -- cgit v1.2.3 From f171efed99684bf03c315405efda34e36d7db82c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 21 Oct 2024 09:31:58 +0000 Subject: Ensure only one instance of global page table can exist --- .../arch/memory/paging/active_page_table.hpp | 32 ----------------- .../include/arch/memory/paging/page_mapper.hpp | 41 +++++++++++++++------- .../include/arch/memory/paging/page_table.hpp | 28 +++++---------- 3 files changed, 38 insertions(+), 63 deletions(-) delete mode 100644 arch/x86_64/include/arch/memory/paging/active_page_table.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp deleted file mode 100644 index 3933d5a..0000000 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP - -#include "arch/memory/paging/page_table.hpp" - -namespace teachos::arch::memory::paging -{ - - struct active_page_table - { - /** - * @brief Ensures only one instance of active_page_table exists. - * - * @param level4_page_table A pointer to the level 4 page table. - * @return The only instance of active_page_table. - */ - auto create(page_table * level4_page_table) -> active_page_table *; - - private: - /** - * @brief Construct a new active page table object. - * - * @param level4_page_table A pointer to the level 4 page table. - */ - active_page_table(page_table * level4_page_table); - - bool instantiated = false; ///< Indicates wether an instance already exists. - page_table * level4_page_table; ///< The active level4 page table. - }; -} // namespace teachos::arch::memory::paging - -#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index ae3502e..ebd044a 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -9,6 +9,15 @@ namespace teachos::arch::memory::paging { + /** + * @brief Creates a single instance of the level 4 page table table and returns it or alternatively returns the + * previously created instance. The instance is owned by this method and is static, meaning it lives on for the + * complete lifetime of the program. + * + * @return Single unique instance of the level 4 page table. + */ + auto create_or_get() -> page_table *; + /** * @brief Translates page into physical frame, will first attempt to parse normally using default page size and if it * failed attempt to parse using huge pages. @@ -49,27 +58,35 @@ namespace teachos::arch::memory::paging auto map_page_to_frame(T & allocator, virtual_page page, allocator::physical_frame frame, std::bitset<64U> flags) -> void { - page_table page_table{}; - bool table_exists = false; + page_table * current_page_table = create_or_get(); for (auto level = page_table::LEVEL4; level != page_table::LEVEL1; level--) { - std::size_t level_index = page.get_level_index(level); - table_exists = page_table.next_table(level_index); - - if (!table_exists) + auto level_index = page.get_level_index(level); + auto next_page_table = current_page_table->next_table(level_index); + // If the next table method failed then it means that the page level of the frame we want allocate has not yet + // been created itself. So we have to do that before we are able to allocate the wanted frame. This has to be done + // for every level, meaning we potenitally create a level 4, level 3 and level 2 page entry, each pointing to a + // page table one level below. + if (!next_page_table) { auto allocated_frame = allocator.allocate_frame(); - exception_handling::assert(!allocated_frame.has_value(), "[Page mapper]: Unable to allocate frame"); - page_table[level_index].set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); - page_table.zero_entries(); + exception_handling::assert(!allocated_frame.has_value(), "[Page mapper] Unable to allocate frame"); + current_page_table->operator[](level_index) + .set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); + // There should now be an entry at the previously not existent index, therefore we can simply access it again. + next_page_table = current_page_table->next_table(page.get_level_index(level)); + exception_handling::assert(!next_page_table.has_value(), + "[Page mapper] Unable to create new entry into page table"); + next_page_table.value()->zero_entries(); } + current_page_table = next_page_table.value(); } - auto level1_entry = page_table[page.get_level_index(page_table::LEVEL1)]; + auto level1_entry = current_page_table->operator[](page.get_level_index(page_table::LEVEL1)); arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE), - "[Page Mapper]: Unable to map huge pages"); - arch::exception_handling::assert(!level1_entry.is_unused(), "[Page Mapper]: Page table entry is already used"); + "[Page Mapper] Unable to map huge pages"); + arch::exception_handling::assert(!level1_entry.is_unused(), "[Page Mapper] Page table entry is already used"); level1_entry.set_entry(frame, flags | std::bitset<64U>{entry::PRESENT}); } } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 0fe667c..3439127 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -10,16 +10,6 @@ namespace teachos::arch::memory::paging constexpr std::size_t PAGE_TABLE_ENTRY_COUNT = 512U; ///< Default entry count of a page table in x86_84 is 512. } - /** - * @brief Actual data that is contained in every page table, this is the structure we cast a specific address too, - * because it consists of x amount os entries, which is a simple address. - */ - struct table_content - { - entry entries[PAGE_TABLE_ENTRY_COUNT]; ///< Entries containing addresses to page tables of a level below or actual - ///< virtual addresses for the level 1 page table. - }; - /** * @brief A Page table containing 512 entries. */ @@ -38,9 +28,10 @@ namespace teachos::arch::memory::paging }; /** - * @brief Constructor. Automatically starts on the fixed address of the Level 4 page table. + * @brief Deleted constructor. Object can only be created by casting from the fixed Level 4 + * page table address `reinterpret_cast(0xfffffffffffff000)`. */ - page_table(); + page_table() = delete; /** * @brief Set every entry of the page to unused. @@ -48,13 +39,13 @@ namespace teachos::arch::memory::paging auto zero_entries() -> void; /** - * @brief Turn this page table into the next page table level from the given page table index. Meaning we - * use an index into a Level 4 page table to get the according Level 3 page table. When using this on an a level 1 - * page table it will cause an assertion. + * @brief Returns the next page table level from the given page table index. Meaning we + * use an index into a Level 4 page table to get the according Level 3 page table. This method should not be called + * on a Level 1 page table or it will return invalid addresses and cause hard to debug issues. * * @param table_index Index of this page table in the page table one level higher. */ - auto next_table(std::size_t table_index) -> bool; + auto next_table(std::size_t table_index) -> std::optional; /** * @brief Index operator overload to access specific mutable entry directy. @@ -83,9 +74,8 @@ namespace teachos::arch::memory::paging */ auto next_table_address(std::size_t table_index) -> std::optional; - level current_level; ///< Current level of the page table, used to ensure next_table() is never called with a level - ///< 1 page table - table_content * current_table; ///< Current table we are accessing and indexing. + entry entries[PAGE_TABLE_ENTRY_COUNT]; ///< Entries containing addresses to page tables of a level below or actual + ///< virtual addresses for the level 1 page table. }; auto operator--(page_table::level & level, int) -> page_table::level; -- cgit v1.2.3 From 72cb015567cb65527e9105e653c001be3c04eab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 21 Oct 2024 12:03:21 +0000 Subject: Use handle struct to ensure next_table is not called on page table level 1 --- .../include/arch/exception_handling/assert.hpp | 2 - .../arch/memory/allocator/area_frame_allocator.hpp | 6 +- .../include/arch/memory/paging/page_mapper.hpp | 29 +++++----- .../include/arch/memory/paging/page_table.hpp | 65 ++++++++++++++++------ .../include/arch/memory/paging/virtual_page.hpp | 2 +- 5 files changed, 67 insertions(+), 37 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/exception_handling/assert.hpp b/arch/x86_64/include/arch/exception_handling/assert.hpp index bfc205c..58c1f33 100644 --- a/arch/x86_64/include/arch/exception_handling/assert.hpp +++ b/arch/x86_64/include/arch/exception_handling/assert.hpp @@ -1,8 +1,6 @@ #ifndef TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_ASSERT_HPP #define TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_ASSERT_HPP -#include "arch/exception_handling/panic.hpp" - namespace teachos::arch::exception_handling { /** 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 f99b7c8..7b1bb16 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,17 +1,17 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP #define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP +#include "arch/memory/allocator/physical_frame.hpp" #include "arch/memory/multiboot/reader.hpp" -#include "physical_frame.hpp" #include namespace teachos::arch::memory::allocator { template - concept FrameAllocator = requires(T t) { + concept FrameAllocator = requires(T t, physical_frame a) { { t.allocate_frame() } -> std::same_as>; - { t.deallocate_frame() } -> std::same_as; + { t.deallocate_frame(a) } -> std::same_as; }; /** diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index ebd044a..a874f75 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -10,13 +10,13 @@ namespace teachos::arch::memory::paging { /** - * @brief Creates a single instance of the level 4 page table table and returns it or alternatively returns the - * previously created instance. The instance is owned by this method and is static, meaning it lives on for the - * complete lifetime of the program. + * @brief Creates a single instance of the level 4 page table table and returns handle to it or alternatively returns + * the previously created handle instead. The instance is owned by this method and is static, meaning it lives on for + * the complete lifetime of the program. * - * @return Single unique instance of the level 4 page table. + * @return Handle to the single unique instance of the level 4 page table. */ - auto create_or_get() -> page_table *; + auto create_or_get() -> page_table_handle; /** * @brief Translates page into physical frame, will first attempt to parse normally using default page size and if it @@ -58,32 +58,31 @@ namespace teachos::arch::memory::paging auto map_page_to_frame(T & allocator, virtual_page page, allocator::physical_frame frame, std::bitset<64U> flags) -> void { - page_table * current_page_table = create_or_get(); + auto current_handle = create_or_get(); for (auto level = page_table::LEVEL4; level != page_table::LEVEL1; level--) { auto level_index = page.get_level_index(level); - auto next_page_table = current_page_table->next_table(level_index); + auto next_handle = current_handle.next_table(level_index); // If the next table method failed then it means that the page level of the frame we want allocate has not yet // been created itself. So we have to do that before we are able to allocate the wanted frame. This has to be done // for every level, meaning we potenitally create a level 4, level 3 and level 2 page entry, each pointing to a // page table one level below. - if (!next_page_table) + if (!next_handle) { auto allocated_frame = allocator.allocate_frame(); exception_handling::assert(!allocated_frame.has_value(), "[Page mapper] Unable to allocate frame"); - current_page_table->operator[](level_index) - .set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); + current_handle[level_index].set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); // There should now be an entry at the previously not existent index, therefore we can simply access it again. - next_page_table = current_page_table->next_table(page.get_level_index(level)); - exception_handling::assert(!next_page_table.has_value(), + next_handle = current_handle.next_table(page.get_level_index(level)); + exception_handling::assert(!next_handle.has_value(), "[Page mapper] Unable to create new entry into page table"); - next_page_table.value()->zero_entries(); + next_handle.value().zero_entries(); } - current_page_table = next_page_table.value(); + current_handle = next_handle.value(); } - auto level1_entry = current_page_table->operator[](page.get_level_index(page_table::LEVEL1)); + auto level1_entry = current_handle[page.get_level_index(page_table::LEVEL1)]; arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE), "[Page Mapper] Unable to map huge pages"); arch::exception_handling::assert(!level1_entry.is_unused(), "[Page Mapper] Page table entry is already used"); diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 3439127..a1c8abe 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -1,7 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP -#include "page_entry.hpp" +#include "arch/memory/paging/page_entry.hpp" namespace teachos::arch::memory::paging { @@ -41,27 +41,20 @@ namespace teachos::arch::memory::paging /** * @brief Returns the next page table level from the given page table index. Meaning we * use an index into a Level 4 page table to get the according Level 3 page table. This method should not be called - * on a Level 1 page table or it will return invalid addresses and cause hard to debug issues. + * on a Level 1 page table, because there is no furthere page table and mangeling up and returning the physical + * address would cause hard to debug issues. * - * @param table_index Index of this page table in the page table one level higher. + * @param table_index Index of this page table in the page table one level lower. */ - auto next_table(std::size_t table_index) -> std::optional; + auto next_table(std::size_t table_index) const -> std::optional; /** - * @brief Index operator overload to access specific mutable entry directy. + * @brief Index operator overload to access specific entries directy. * - * @param index Index of the entry we want to access and change. + * @param index Index of the entry we want to access and read or write too. * @return Entry at the given table index. */ - auto operator[](std::size_t index) -> entry &; - - /** - * @brief Index operator overload to access specific immutable entry directy. - * - * @param index Index of the entry we want to access and only read. - * @return Entry at the given table index. - */ - auto operator[](std::size_t index) const -> entry const &; + auto operator[](std::size_t index) const -> entry; private: /** @@ -72,13 +65,53 @@ namespace teachos::arch::memory::paging * @param table_index Index of this page table in the page table one level higher. * @return An optional of the address of the next page table or null. */ - auto next_table_address(std::size_t table_index) -> std::optional; + auto next_table_address(std::size_t table_index) const -> std::optional; entry entries[PAGE_TABLE_ENTRY_COUNT]; ///< Entries containing addresses to page tables of a level below or actual ///< virtual addresses for the level 1 page table. }; auto operator--(page_table::level & level, int) -> page_table::level; + + /** + * @brief Handle that ensures accessing the page table is safe because it adds additional checks to the next_table + * method and ensures it can only be called if the table level is not LEVEL1. + */ + struct page_table_handle + { + /** + * @brief Constructor. + */ + page_table_handle(page_table * handle, page_table::level handle_level); + + /** + * @brief Set every entry of the page to unused. + */ + auto zero_entries() -> void; + + /** + * @brief Returns the next page table level from the given page table index. Meaning we + * use an index into a Level 4 page table to get the according Level 3 page table. If this method is called with a + * Level 1 page table it will instead assert and halt execution, because there is no furthere page table and + * mangeling up and returning the physical address would cause hard to debug issues. + * + * @param table_index Index of this page table in the page table one level lower. + */ + auto next_table(std::size_t table_index) const -> std::optional; + + /** + * @brief Index operator overload to access specific immutable entry directy. + * + * @param index Index of the entry we want to access and only read. + * @return Entry at the given table index. + */ + auto operator[](std::size_t index) const -> entry; + + private: + page_table * handle; ///< Handle to underlying page table, can never be null (invariant ensured by constructor) + page_table::level handle_level; ///< Level page table is currently on, depends on how often next_level was + ///< called successfully. + }; } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index 6b9a641..f8dfbf0 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -2,8 +2,8 @@ #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP #include "arch/memory/allocator/physical_frame.hpp" +#include "arch/memory/paging/page_table.hpp" -#include "page_table.hpp" #include #include #include -- cgit v1.2.3 From 552477a12a1163f0f80801b4055dcb5ab3f79e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 21 Oct 2024 12:53:23 +0000 Subject: Use forward declaration to hide actual page_table --- .../include/arch/memory/paging/page_mapper.hpp | 4 +- .../include/arch/memory/paging/page_table.hpp | 77 ++++++---------------- .../include/arch/memory/paging/virtual_page.hpp | 2 +- 3 files changed, 22 insertions(+), 61 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index a874f75..0806f58 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -60,7 +60,7 @@ namespace teachos::arch::memory::paging { auto current_handle = create_or_get(); - for (auto level = page_table::LEVEL4; level != page_table::LEVEL1; level--) + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; level--) { auto level_index = page.get_level_index(level); auto next_handle = current_handle.next_table(level_index); @@ -82,7 +82,7 @@ namespace teachos::arch::memory::paging current_handle = next_handle.value(); } - auto level1_entry = current_handle[page.get_level_index(page_table::LEVEL1)]; + auto level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE), "[Page Mapper] Unable to map huge pages"); arch::exception_handling::assert(!level1_entry.is_unused(), "[Page Mapper] Page table entry is already used"); diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index a1c8abe..91ce81c 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -11,12 +11,20 @@ namespace teachos::arch::memory::paging } /** - * @brief A Page table containing 512 entries. + * @brief Forward delcaration of the page_table, because it should only be accessible over the handle, the actual + * methods or constructor are not defined meaning they are not callable from outside. Instead the struct is only fully + * defined in the implementation (.cpp) file of the page table, and therefore also only accesible in that file. */ - struct page_table + struct page_table; + + /** + * @brief Handle that ensures accessing the page table is safe because it adds additional checks to the next_table + * method and ensures it can only be called if the table level is not LEVEL1. + */ + struct page_table_handle { /** - * @brief Level of the page table, level 1 should not be able to call next_table anymore, because it would result in + * @brief Level of the page table, level 1 will not be able to call next_table anymore, because it would result in * attempting to access memory that it should not. */ enum level : uint8_t @@ -27,62 +35,13 @@ namespace teachos::arch::memory::paging LEVEL4 }; - /** - * @brief Deleted constructor. Object can only be created by casting from the fixed Level 4 - * page table address `reinterpret_cast(0xfffffffffffff000)`. - */ - page_table() = delete; - - /** - * @brief Set every entry of the page to unused. - */ - auto zero_entries() -> void; - - /** - * @brief Returns the next page table level from the given page table index. Meaning we - * use an index into a Level 4 page table to get the according Level 3 page table. This method should not be called - * on a Level 1 page table, because there is no furthere page table and mangeling up and returning the physical - * address would cause hard to debug issues. - * - * @param table_index Index of this page table in the page table one level lower. - */ - auto next_table(std::size_t table_index) const -> std::optional; - - /** - * @brief Index operator overload to access specific entries directy. - * - * @param index Index of the entry we want to access and read or write too. - * @return Entry at the given table index. - */ - auto operator[](std::size_t index) const -> entry; - - private: - /** - * @brief Calculates the address of the next page table level for the given table index. The next page table address - * is only valid if the corresponding entry is present and not a huge page. Meaning we use an index into a - * Level 4 page table to get the according Level 3 page table address. - * - * @param table_index Index of this page table in the page table one level higher. - * @return An optional of the address of the next page table or null. - */ - auto next_table_address(std::size_t table_index) const -> std::optional; - - entry entries[PAGE_TABLE_ENTRY_COUNT]; ///< Entries containing addresses to page tables of a level below or actual - ///< virtual addresses for the level 1 page table. - }; - - auto operator--(page_table::level & level, int) -> page_table::level; - - /** - * @brief Handle that ensures accessing the page table is safe because it adds additional checks to the next_table - * method and ensures it can only be called if the table level is not LEVEL1. - */ - struct page_table_handle - { /** * @brief Constructor. + * + * @param handle Underlying page table the handle should point to. + * @param handle_level Level the underlying page table is on, used to ensure safety. */ - page_table_handle(page_table * handle, page_table::level handle_level); + page_table_handle(page_table * handle, level handle_level); /** * @brief Set every entry of the page to unused. @@ -109,9 +68,11 @@ namespace teachos::arch::memory::paging private: page_table * handle; ///< Handle to underlying page table, can never be null (invariant ensured by constructor) - page_table::level handle_level; ///< Level page table is currently on, depends on how often next_level was - ///< called successfully. + level handle_level; ///< Level page table is currently on, depends on how often next_level was + ///< called successfully. }; + + auto operator--(page_table_handle::level & level, int) -> page_table_handle::level; } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index f8dfbf0..ca11b3c 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -43,7 +43,7 @@ namespace teachos::arch::memory::paging * @param level Level of the page table we want to calculate the index for. * @return Index into the page table with the given level. */ - auto get_level_index(page_table::level level) const -> uint64_t; + auto get_level_index(page_table_handle::level level) const -> uint64_t; /** * @brief Defaulted equals operator. -- cgit v1.2.3 From 039f12eb2f5785357ab1745201c8d420ab644165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 21 Oct 2024 13:35:10 +0000 Subject: Adding more mapping methods --- .../include/arch/memory/paging/page_mapper.hpp | 60 ++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 0806f58..0f226e2 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -48,6 +48,8 @@ namespace teachos::arch::memory::paging * entry in every page level if it does not exists yet down to level 1. If the level 1 page table already exists it * halts execution instead. * + * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and + * deallocate method. * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate entries * when a new page table is required. * @param page Virtual page that is being mapped. @@ -88,6 +90,64 @@ namespace teachos::arch::memory::paging arch::exception_handling::assert(!level1_entry.is_unused(), "[Page Mapper] Page table entry is already used"); level1_entry.set_entry(frame, flags | std::bitset<64U>{entry::PRESENT}); } + + /** + * @brief Allocates the next free frame and then uses that frame to call map_page_to_frame. + */ + template + auto map_next_free_page_to_frame(T & allocator, virtual_page page, std::bitset<64U> flags) -> void + { + auto frame = allocator.allocate_frame(); + exception_handling::assert(!frame.has_value(), "[Page mapper] Out of memory exception"); + map_page_to_frame(allocator, page, frame.value(), flags); + } + + /** + * @brief Gets the corresponding page the given frame has to be contained in and uses that to call map_page_to_frame. + */ + template + auto identity_map(T & allocator, allocator::physical_frame frame, std::bitset<64U> flags) -> void + { + auto page = virtual_page::containing_address(frame.start_address()); + map_page_to_frame(allocator, page, frame, flags); + } + + /** + * @brief Unmaps the virtual page from the previously mapped to physical frame and resets the flags. Deallocates and + * unmaps the entry in every page level if this page was the last one up to level 4. + * + * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and + * deallocate method. + * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate entries + * when a new page table is required. + * @param page Virtual page that is being unmapped. + */ + template + auto unmap_page(T & allocator, virtual_page page) -> void + { + exception_handling::assert(translate_page(page).has_value(), + "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); + + auto current_handle = create_or_get(); + + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; level--) + { + auto level_index = page.get_level_index(level); + auto next_handle = current_handle.next_table(level_index); + // The next table method failed even tough the page has to be mapped already, because translate_page did not fail. + // This can only mean that we attempted to unmap a huge page, which is not supported in the first place. + exception_handling::assert(next_handle.has_value(), "[Page Mapper] Unable to unmap huge pages"); + current_handle = next_handle.value(); + } + + auto level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; + auto level1_frame = level1_entry.calculate_pointed_to_frame(); + exception_handling::assert(level1_frame.has_value(), + "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); + level1_entry.set_unused(); + // TODO: Deallocate and unmap level 1, 2, 3 page table entry if this was the last page in them. + allocator.deallocate_frame(level1_frame.value()); + } } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP -- cgit v1.2.3 From 8502cc9b19a9e934e3a4c0b3190b690ee0407a25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 21 Oct 2024 14:48:03 +0000 Subject: =?UTF-8?q?Fix=20linker=20error=20using=20friend=20method=20?= =?UTF-8?q?=F0=9F=91=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../arch/memory/allocator/physical_frame.hpp | 2 +- .../include/arch/memory/paging/page_mapper.hpp | 2 ++ .../include/arch/memory/paging/page_table.hpp | 22 ++++++++++++++++------ .../include/arch/memory/paging/virtual_page.hpp | 2 +- 4 files changed, 20 insertions(+), 8 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp index e013e0d..e33c77a 100644 --- a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp +++ b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp @@ -27,7 +27,7 @@ namespace teachos::arch::memory::allocator * @param physical_address Physical 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 physical_address) -> physical_frame; + auto static containing_address(std::size_t physical_address) -> physical_frame; /** * @brief Evaluates the start address of the physical frame. diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 0f226e2..a8cca4c 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -145,7 +145,9 @@ namespace teachos::arch::memory::paging exception_handling::assert(level1_frame.has_value(), "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); level1_entry.set_unused(); + // TODO: Flush the translation lookaside buffer to clear the entry from cache as well. (mov cr3, cr3) // TODO: Deallocate and unmap level 1, 2, 3 page table entry if this was the last page in them. + // TODO: Fix deallocate because it is not yet implemented. allocator.deallocate_frame(level1_frame.value()); } } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 91ce81c..3a31dc5 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -5,10 +5,7 @@ namespace teachos::arch::memory::paging { - namespace - { - constexpr std::size_t PAGE_TABLE_ENTRY_COUNT = 512U; ///< Default entry count of a page table in x86_84 is 512. - } + constexpr std::size_t PAGE_TABLE_ENTRY_COUNT = 512U; ///< Default entry count of a page table in x86_84 is 512. /** * @brief Forward delcaration of the page_table, because it should only be accessible over the handle, the actual @@ -66,13 +63,26 @@ namespace teachos::arch::memory::paging */ auto operator[](std::size_t index) const -> entry; + /** + * @brief Decrements the page table handle level enum by one, is defined so we can use it as a replacement for an + * int index in a range based for loop. Will halt execution if called with page_table_handle::LEVEL1, because there + * is no level below. Has to be defined as either a friend function or inline header method, because we define an + * operator of another type. In this instance friend function was choosen, because the struct itself also requires + * the operator, but declaring before the struct is not possible, because the enum is in the struct. This is + * inpossible because the struct requires the operator declared before itself to work, and the operator requires the + * struct declared before itself to work. Furthermore this allows the defintion of the method to be done in the cpp, + * avoiding includes in the header file. + * + * @param value Value we want to decrement on + * @return level New level value decrement by one, meaning the level is also decrement by one Level4 --> Level3, ... + */ + friend auto operator--(level value, int) -> level; + private: page_table * handle; ///< Handle to underlying page table, can never be null (invariant ensured by constructor) level handle_level; ///< Level page table is currently on, depends on how often next_level was ///< called successfully. }; - - auto operator--(page_table_handle::level & level, int) -> page_table_handle::level; } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index ca11b3c..79801ee 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -28,7 +28,7 @@ namespace teachos::arch::memory::paging * @param virtual_address Virtual address we want to get the corresponding virtual page for. * @return Frame the given address is contained in. */ - static auto containing_address(std::size_t virtual_address) -> virtual_page; + auto static containing_address(std::size_t virtual_address) -> virtual_page; /** * @brief Evaluates the start address of the virtual page. -- cgit v1.2.3 From f9cc4f123e224b28ac2d879ab92cf60f1df351e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 21 Oct 2024 14:52:03 +0000 Subject: Use enum struct instead of class for uniformity --- arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp | 2 +- arch/x86_64/include/arch/memory/multiboot/info.hpp | 2 +- arch/x86_64/include/arch/memory/multiboot/memory_map.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp index 88d211e..72767a8 100644 --- a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp @@ -11,7 +11,7 @@ namespace teachos::arch::memory::multiboot * @brief Defines all elf section types an elf section header can have. See * https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information. */ - enum class elf_section_type : uint32_t + enum struct elf_section_type : uint32_t { INACTIVE, ///< (SHT_NULL) Unused, meaning all values are zeroed out PROGRAMM, ///< (SHT_PROGBITS) Program data (DATA, CODE) diff --git a/arch/x86_64/include/arch/memory/multiboot/info.hpp b/arch/x86_64/include/arch/memory/multiboot/info.hpp index ca87834..a0f095f 100644 --- a/arch/x86_64/include/arch/memory/multiboot/info.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/info.hpp @@ -12,7 +12,7 @@ namespace teachos::arch::memory::multiboot * tag headers and see https://github.com/rhboot/grub2/blob/fedora-39/include/multiboot.h for more information on the * actual header contents and their following data. */ - enum class tag_type : uint32_t + enum struct tag_type : uint32_t { END, ///< Signals final tag for the multiboot2 information structure CMDLINE, ///< Contains the command line string diff --git a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp index 4dc11cf..ecf3975 100644 --- a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp @@ -9,7 +9,7 @@ namespace teachos::arch::memory::multiboot /** * @brief Defines all memory area types possible that the memory region can be in. */ - enum class memory_area_type : uint32_t + enum struct memory_area_type : uint32_t { AVAILABLE = 1, ///< Region is available for use by the OS RESERVED, ///< Region is reserved by firmware or bootloader and should not be used by OS -- cgit v1.2.3 From 7d1d7c5f63791506049cc188740cc4956fc8d14c Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 22 Oct 2024 05:37:28 +0000 Subject: update comments --- .../include/arch/memory/paging/page_table.hpp | 30 ++++++++++++---------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 3a31dc5..9aaaafb 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -21,7 +21,9 @@ namespace teachos::arch::memory::paging struct page_table_handle { /** - * @brief Level of the page table, level 1 will not be able to call next_table anymore, because it would result in + * @brief Level of the page table. + * + * Level 1 will not be able to call next_table anymore, because it would result in * attempting to access memory that it should not. */ enum level : uint8_t @@ -46,10 +48,11 @@ namespace teachos::arch::memory::paging auto zero_entries() -> void; /** - * @brief Returns the next page table level from the given page table index. Meaning we - * use an index into a Level 4 page table to get the according Level 3 page table. If this method is called with a - * Level 1 page table it will instead assert and halt execution, because there is no furthere page table and - * mangeling up and returning the physical address would cause hard to debug issues. + * @brief Returns the next page table level from the given page table index. + * + * Meaning we use an index into a Level 4 page table to get the according Level 3 page table. If this method is + * called with a Level 1 page table it will instead assert and halt execution, because there is no furthere page + * table and mangeling up and returning the physical address would cause hard to debug issues. * * @param table_index Index of this page table in the page table one level lower. */ @@ -64,14 +67,15 @@ namespace teachos::arch::memory::paging auto operator[](std::size_t index) const -> entry; /** - * @brief Decrements the page table handle level enum by one, is defined so we can use it as a replacement for an - * int index in a range based for loop. Will halt execution if called with page_table_handle::LEVEL1, because there - * is no level below. Has to be defined as either a friend function or inline header method, because we define an - * operator of another type. In this instance friend function was choosen, because the struct itself also requires - * the operator, but declaring before the struct is not possible, because the enum is in the struct. This is - * inpossible because the struct requires the operator declared before itself to work, and the operator requires the - * struct declared before itself to work. Furthermore this allows the defintion of the method to be done in the cpp, - * avoiding includes in the header file. + * @brief Decrements the page table handle level enum by one. + * + * Is defined so we can use it as a replacement for an int index in a range based for loop. Will halt execution if + * called with page_table_handle::LEVEL1, because there is no level below. Has to be defined as either a friend + * function or inline header method, because we define an operator of another type. In this instance friend function + * was choosen, because the struct itself also requires the operator, but declaring before the struct is not + * possible, because the enum is in the struct. This is inpossible because the struct requires the operator declared + * before itself to work, and the operator requires the struct declared before itself to work. Furthermore this + * allows the defintion of the method to be done in the cpp, avoiding includes in the header file. * * @param value Value we want to decrement on * @return level New level value decrement by one, meaning the level is also decrement by one Level4 --> Level3, ... -- cgit v1.2.3 From ba054441f93a30e2042a71d632a6a5fb04007d15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 22 Oct 2024 06:16:51 +0000 Subject: Adjust all briefs --- .../arch/memory/allocator/area_frame_allocator.hpp | 2 +- .../arch/memory/multiboot/elf_symbols_section.hpp | 108 +++++++++++---------- arch/x86_64/include/arch/memory/multiboot/info.hpp | 55 +++++------ .../include/arch/memory/multiboot/memory_map.hpp | 34 ++++--- .../include/arch/memory/multiboot/reader.hpp | 11 ++- .../include/arch/memory/paging/page_entry.hpp | 16 +-- .../include/arch/memory/paging/page_mapper.hpp | 17 +++- .../include/arch/memory/paging/page_table.hpp | 33 ++++--- arch/x86_64/include/arch/video/vga/text.hpp | 26 ++--- 9 files changed, 162 insertions(+), 140 deletions(-) (limited to 'arch/x86_64/include') 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 7b1bb16..a1b771e 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 @@ -29,7 +29,7 @@ namespace teachos::arch::memory::allocator /** * @brief Allocate memory by finding and returning a free physical_frame. * - * The physical_frame allocation executes multiple checks before returning + * @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 diff --git a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp index 72767a8..fc8cb15 100644 --- a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp @@ -8,33 +8,35 @@ namespace teachos::arch::memory::multiboot { /** - * @brief Defines all elf section types an elf section header can have. See - * https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information. + * @brief Defines all elf section types an elf section header can have. + * + * @note See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information. */ enum struct elf_section_type : uint32_t { - INACTIVE, ///< (SHT_NULL) Unused, meaning all values are zeroed out - PROGRAMM, ///< (SHT_PROGBITS) Program data (DATA, CODE) - SYMBOL_TABLE, ///< (SHT_SYMBTAB) Contains actual entries pointed to in symbol hash table - STRING_TABLE, ///< (SHT_STRTAB) Contains symbols, section and deubbging null-terminated strings - RELOCATION_ENTRY_WITH_ADDENDS, ///< (SHT_RELA) Only used on 64 bit systems - SYMBOL_HASH_TABLE, ///< (SHT_HASH) Hash table used by dynamic linker to locate symbols - DYNAMIC, ///< (SHT_DYNAMIC) Contains dynamic linking information - NOTE, ///< (SHT_NOTE) Stores information that marks files in some way - EMPTY, ///< (SHT_NOBITS) Program data section, that occupies no space in the file (.bss) - RELOCATION_ENTRY_WITHOUT_ADDENDS, ///< (SHT_REL) Only used on 32 bit systems - UNSPECIFIED, ///< (SHT_SHLIB) Reserved but has unspecified semantics - DYNAMIC_SYMBOL_TABLE, ///< (SHT_DYNSYM) Holds minimal set of symbols adequate for dynamic linking - INITALIZATION_FUNCTION_ARRAY = 14, ///< (SHT_INIT_ARRAY) Array of pointers to intialization functions () -> void - TERMINATION_FUNCTION_ARRAY, ///< (SHT_FINI_ARRAY) Array of pointers to termination functions () -> void + INACTIVE, ///< (SHT_NULL) Unused, meaning all values are zeroed out. + PROGRAMM, ///< (SHT_PROGBITS) Program data (DATA, CODE). + SYMBOL_TABLE, ///< (SHT_SYMBTAB) Contains actual entries pointed to in symbol hash table. + STRING_TABLE, ///< (SHT_STRTAB) Contains symbols, section and deubbging null-terminated strings. + RELOCATION_ENTRY_WITH_ADDENDS, ///< (SHT_RELA) Only used on 64 bit systems. + SYMBOL_HASH_TABLE, ///< (SHT_HASH) Hash table used by dynamic linker to locate symbols. + DYNAMIC, ///< (SHT_DYNAMIC) Contains dynamic linking information. + NOTE, ///< (SHT_NOTE) Stores information that marks files in some way. + EMPTY, ///< (SHT_NOBITS) Program data section, that occupies no space in the file (.bss). + RELOCATION_ENTRY_WITHOUT_ADDENDS, ///< (SHT_REL) Only used on 32 bit systems. + UNSPECIFIED, ///< (SHT_SHLIB) Reserved but has unspecified semantics. + DYNAMIC_SYMBOL_TABLE, ///< (SHT_DYNSYM) Holds minimal set of symbols adequate for dynamic linking. + INITALIZATION_FUNCTION_ARRAY = 14, ///< (SHT_INIT_ARRAY) Array of pointers to intialization functions () -> void. + TERMINATION_FUNCTION_ARRAY, ///< (SHT_FINI_ARRAY) Array of pointers to termination functions () -> void. PRE_INITALIZATION_FUNCTION_ARRAY ///< (SHT_PRE_INIT_ARRAY) Array of pointers to functions invoked before other - ///< initalization functions () -> void + ///< initalization functions () -> void. }; /** * @brief Defines helper function for all states that the elf section flags of an elf section header can - * have. See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html - * See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information. + * have. + * + * @note See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information. */ struct elf_section_flags { @@ -63,9 +65,9 @@ namespace teachos::arch::memory::multiboot COMPRESSED = 1U << 11U, ///< (SHF_COMPRESSED) Section contains compressed data. SPECIAL_ORDERING_REQUIREMENTS = 1U << 30U, ///< (SHF_ORDERED) Section has special ordering requirements, meaning it - ///< should be ordered in relation to other sections of the same type + ///< should be ordered in relation to other sections of the same type. EXCLUDED_UNLESS_REFERENCED_OR_ALLOCATED = 1U << 31U, ///< (SHF_EXCLUDE)Section is excluded unless referenced or - ///< allocated, used for LTO (Link-Time Optimizations) + ///< allocated, used for LTO (Link-Time Optimizations). }; /** @@ -81,20 +83,21 @@ namespace teachos::arch::memory::multiboot } /** - * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset, meaning that all - * bits that are set in the given std::bitset also have to be set in the underlyng std::bitset. Any additional bits - * that are set are not relevant. + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. + * + * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng + * std::bitset. Any additional bits that are set are not relevant. * * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. - * @return Whether the given flags are a subset or equivalent with the underlying std::bitset + * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. */ auto contains_flags(std::bitset<64U> other) const -> bool; /** - * @brief Allows to compare the underlying std::bitset of two instances + * @brief Allows to compare the underlying std::bitset of two instances. * - * @param other Other instance that we want to compare with - * @return Whether the underlying std::bitset of both types is the same + * @param other Other instance that we want to compare with. + * @return Whether the underlying std::bitset of both types is the same. */ auto operator==(elf_section_flags const & other) const -> bool = default; @@ -106,33 +109,35 @@ namespace teachos::arch::memory::multiboot /** * @brief Defines the data included in a section header, where each section has exactly one section header. - * See https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html for more information + * + * @note See https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html for more information. */ struct elf_section_header { - uint32_t name_table_index; ///< Index into the section header string table, specifies the name of the section - elf_section_type type; ///< Categorizes the sections content and semantics - elf_section_flags flags; ///< 1-bit flgas that describe section attributes + uint32_t name_table_index; ///< Index into the section header string table, specifies the name of the section. + elf_section_type type; ///< Categorizes the sections content and semantics. + elf_section_flags flags; ///< 1-bit flgas that describe section attributes. uint64_t virtual_address; ///< If section appears in memory image of a process, gives address at which the sections - ///< first byte should reside, otherwise 0 + ///< first byte should reside, otherwise 0. uint64_t file_offset; ///< Offset from the beginning of the file to the first byte in the section. SHT_NOBITS - ///< contains the conceptual placement instead (because it occupies no space in the file) - uint64_t section_size; ///< Complete section size in bytes, SHT_NOBITS may have non-zero value but will always - ///< occupy no space in the file - uint32_t other_section; ///< Section header table index link, behaviour varies on type - ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link + ///< contains the conceptual placement instead (because it occupies no space in the file). + uint64_t section_size; ///< Complete section size in bytes, SHT_NOBITS may have non-zero value but will always + ///< occupy no space in the file. + uint32_t other_section; ///< Section header table index link, behaviour varies on type + ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link. uint32_t additional_information; ///< Extra information, behaviour varies on type - ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link + ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link. uint64_t address_alignment; ///< Possible address alignment constraints. Value of virutal_address must be 0 % value - ///< of address_alignment. Value 0 or 1 mean no alignment constraints + ///< of address_alignment. Value 0 or 1 mean no alignment constraints. uint64_t fixed_table_entry_size; ///< If sections holds table with fixed-sized entries, this gives the size in - ///< bytes of each entry + ///< bytes of each entry. /** * @brief Detect whether a section header is inactive or not, should always be the case for the first entry in the - * sections table + * sections table. + * * @return Whether the current section header is actually null or not, requires all fields besides section_size and - * other_section to contain 0 + * other_section to contain 0. */ auto is_null() const -> bool; }; @@ -140,17 +145,18 @@ namespace teachos::arch::memory::multiboot /** * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type * multi_boot_tag_type::ELF_SECTIONS. - * The first section in the sections array will always be INACTIVE, there can only ever be one DYNAMIC section and - * only either one DYNAMIC_SYMBOL_TABLE or SYMBOL_TABLE. + * + * @note The first section in the sections array will always be INACTIVE, there can only ever be one DYNAMIC section + * and only either one DYNAMIC_SYMBOL_TABLE or SYMBOL_TABLE. */ struct elf_symbols_section_header { - tag info; ///< Basic multi_boot_tag information - uint32_t number_of_sections; ///< Number of sections in the sections array - uint32_t entry_size; ///< Size of each entry in the sections array - uint32_t section_index; ///< Index to the string table used for symbol names - std::byte end; ///< Marks the end of the tag, used to mark the beginning of any additional data - ///< contained in the section, to ensure byte alignment is actually 4 byte + tag info; ///< Basic multi_boot_tag information. + uint32_t number_of_sections; ///< Number of sections in the sections array. + uint32_t entry_size; ///< Size of each entry in the sections array. + uint32_t section_index; ///< Index to the string table used for symbol names. + std::byte end; ///< Marks the end of the tag, used to mark the beginning of any additional data. + ///< contained in the section, to ensure byte alignment is actually 4 byte. }; } // namespace teachos::arch::memory::multiboot diff --git a/arch/x86_64/include/arch/memory/multiboot/info.hpp b/arch/x86_64/include/arch/memory/multiboot/info.hpp index a0f095f..7924993 100644 --- a/arch/x86_64/include/arch/memory/multiboot/info.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/info.hpp @@ -7,35 +7,36 @@ namespace teachos::arch::memory::multiboot { /** * @brief Defines all possible types a multiboot2 tag structure can have. - * See + * + * @note See * https://github.com/rhboot/grub2/blob/fedora-39/include/multiboot2.h for more information on the structure of the * tag headers and see https://github.com/rhboot/grub2/blob/fedora-39/include/multiboot.h for more information on the * actual header contents and their following data. */ enum struct tag_type : uint32_t { - END, ///< Signals final tag for the multiboot2 information structure - CMDLINE, ///< Contains the command line string - BOOT_LOADER_NAME, ///< Contains the name of the boot loader booting the kernel - MODULE, ///< Indicates the boot module which was loaded along the kernel image - BASIC_MEMORY_INFO, ///< Contains the amount of lower (0MB start address) and upper memory (1MB start address) - BOOTDEV, ///< Indicates which BIOS disk device the hoot loader has loaded the OS image from - MEMORY_MAP, ///< Describes the memory layout of the system with individual areas and their flags - VBE_INFO, ///< Includes information to access and utilize the device GPU - FRAMEBUFFER, ///< VBE framebuffer information - ELF_SECTIONS, ///< Includes list of all section headers from the loaded ELF kernel - APM_INFO, ///< Advanced Power Management information - EFI32, ///< EFI 32 bit system table pointer - EFI64, ///< EFI 64 bit system table pointer - SMBIOS, ///< Contains copy of all Sytem Management BIOS tables - ACPI_OLD, ///< Contains copy of RSDP as defined per ACPI1.0 specification - ACPI_NEW, ///< Contains copy of RSDP as defined per ACPI2.0 or later specification - NETWORK, ///< Contains network information specified specified as DHCP - EFI_MEMORY_MAP, ///< Contains EFI memory map - EFI_BS_NOT_TERMINATED, ///< Indicated ExitBootServies wasn't called - EFI32_IMAGE_HANDLE, ///< EFI 32 bit image handle pointer - EFI64_IMAGE_HANDLE, ///< EFI 64 bit imae handle pointer - LOAD_BASE_ADDRESS ///< Contains image load base physical address + END, ///< Signals final tag for the multiboot2 information structure. + CMDLINE, ///< Contains the command line string. + BOOT_LOADER_NAME, ///< Contains the name of the boot loader booting the kernel. + MODULE, ///< Indicates the boot module which was loaded along the kernel image. + BASIC_MEMORY_INFO, ///< Contains the amount of lower (0MB start address) and upper memory (1MB start address). + BOOTDEV, ///< Indicates which BIOS disk device the hoot loader has loaded the OS image from. + MEMORY_MAP, ///< Describes the memory layout of the system with individual areas and their flags. + VBE_INFO, ///< Includes information to access and utilize the device GPU. + FRAMEBUFFER, ///< VBE framebuffer information. + ELF_SECTIONS, ///< Includes list of all section headers from the loaded ELF kernel. + APM_INFO, ///< Advanced Power Management information. + EFI32, ///< EFI 32 bit system table pointer. + EFI64, ///< EFI 64 bit system table pointer. + SMBIOS, ///< Contains copy of all Sytem Management BIOS tables. + ACPI_OLD, ///< Contains copy of RSDP as defined per ACPI1.0 specification. + ACPI_NEW, ///< Contains copy of RSDP as defined per ACPI2.0 or later specification. + NETWORK, ///< Contains network information specified specified as DHCP. + EFI_MEMORY_MAP, ///< Contains EFI memory map. + EFI_BS_NOT_TERMINATED, ///< Indicated ExitBootServies wasn't called. + EFI32_IMAGE_HANDLE, ///< EFI 32 bit image handle pointer. + EFI64_IMAGE_HANDLE, ///< EFI 64 bit imae handle pointer. + LOAD_BASE_ADDRESS ///< Contains image load base physical address. }; /** @@ -44,8 +45,8 @@ namespace teachos::arch::memory::multiboot */ struct tag { - tag_type type; ///< Specific type of this multi_boot_tag entry, used to differentiate handling - uint32_t size; ///< Total size of this multi_boot_tag entry with all fields of the actual type + tag_type type; ///< Specific type of this multi_boot_tag entry, used to differentiate handling. + uint32_t size; ///< Total size of this multi_boot_tag entry with all fields of the actual type. }; /** @@ -54,8 +55,8 @@ namespace teachos::arch::memory::multiboot */ struct info_header { - uint32_t total_size; ///< Total size of all multiboot::tags and their data - alignas(8) struct tag tags; ///< Specific tags + uint32_t total_size; ///< Total size of all multiboot::tags and their data. + alignas(8) struct tag tags; ///< Specific tags. }; } // namespace teachos::arch::memory::multiboot diff --git a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp index ecf3975..1a38a30 100644 --- a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp @@ -11,25 +11,27 @@ namespace teachos::arch::memory::multiboot */ enum struct memory_area_type : uint32_t { - AVAILABLE = 1, ///< Region is available for use by the OS - RESERVED, ///< Region is reserved by firmware or bootloader and should not be used by OS - ACPI_AVAILABLE, ///< Region is reclaimable by OS after ACPI event - RESERVED_HIBERNATION, ///< Region is used for Non-volatile Storage (NVS) - DEFECTIVE ///< Region is defective or unusable + AVAILABLE = 1, ///< Region is available for use by the OS. + RESERVED, ///< Region is reserved by firmware or bootloader and should not be used by OS. + ACPI_AVAILABLE, ///< Region is reclaimable by OS after ACPI event. + RESERVED_HIBERNATION, ///< Region is used for Non-volatile Storage (NVS). + DEFECTIVE ///< Region is defective or unusable. }; /** - * @brief Defines an entry in the entries array of the memory_map struct. Has to have all padding stripped between the - * individual values, because the size of the entry needs to be exactly 24 bytes and not one byte more. See + * @brief Defines an entry in the entries array of the memory_map struct. + * + * @note Has to have all padding stripped between the individual values, because the size of the entry needs to be + * exactly 24 bytes and not one byte more. See * https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Packed-Structures.html for more information on the * used attribute. */ struct __attribute__((packed)) memory_area { - uint32_t size; ///< Size of this structure in bytes - uint64_t base_address; ///< Base address the memory region starts at - uint64_t area_length; ///< Size of the memory region, added to base_address results in the final address - memory_area_type type; ///< Specific type of memory the region can contain + uint32_t size; ///< Size of this structure in bytes. + uint64_t base_address; ///< Base address the memory region starts at. + uint64_t area_length; ///< Size of the memory region, added to base_address results in the final address. + memory_area_type type; ///< Specific type of memory the region can contain. }; /** @@ -38,10 +40,10 @@ namespace teachos::arch::memory::multiboot */ struct memory_map_header { - tag info; ///< Basic multi_boot_tag information - uint32_t entry_size; ///< Size of each entry in the memory_area array. Guaranteed multiple of 8 - uint32_t entry_version; ///< Version of the entries, currently 0 - struct memory_area entries; ///< Specific memory regions + tag info; ///< Basic multi_boot_tag information. + uint32_t entry_size; ///< Size of each entry in the memory_area array. Guaranteed multiple of 8. + uint32_t entry_version; ///< Version of the entries, currently 0. + struct memory_area entries; ///< Specific memory regions. }; /** @@ -64,7 +66,7 @@ namespace teachos::arch::memory::multiboot memory_area & operator*() const; /** - * @brief Post increment operator. Returns a copy of the value + * @brief Post increment operator. Returns a copy of the value. * * @return Copy of the incremented underlying address. */ diff --git a/arch/x86_64/include/arch/memory/multiboot/reader.hpp b/arch/x86_64/include/arch/memory/multiboot/reader.hpp index 2f72980..393db8b 100644 --- a/arch/x86_64/include/arch/memory/multiboot/reader.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/reader.hpp @@ -22,11 +22,12 @@ namespace teachos::arch::memory::multiboot }; /** - * @brief Reads the relevant multiboot2 information data from memory. This is done using the - * multiboot_information_pointer, which marks the start of the multiboot2 data. The indivdual headers we have to read - * are 8 byte aligned, whereas the data contained in those headers does not have to be. All sections that are read - * additionaly receive some sanity to ensure the read address is actually pointing to the expected structure, if they - * are not this method will assert. + * @brief Reads the relevant multiboot2 information data from memory. + * + * @note This is done using the multiboot_information_pointer, which marks the start of the multiboot2 data. The + * indivdual headers we have to read are 8 byte aligned, whereas the data contained in those headers does not have to + * be. All sections that are read additionaly receive some sanity to ensure the read address is actually pointing to + * the expected structure, if they are not this method will assert. * * The memory_information variables are calcualted like this: * - kernel_start: Calculated by getting the lowest address specified in the elf symbols headers. diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index 158af2e..2b3b3f3 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -64,20 +64,22 @@ namespace teachos::arch::memory::paging auto set_entry(allocator::physical_frame frame, std::bitset<64U> flags) -> void; /** - * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset, meaning that all - * bits that are set in the given std::bitset also have to be set in the underlyng std::bitset. Any additional bits - * that are set are not relevant. + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. + * + * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng + * std::bitset. Any additional bits that are set are not relevant. * * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. - * @return Whether the given flags are a subset or equivalent with the underlying std::bitset + * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. */ auto contains_flags(std::bitset<64U> other) const -> bool; 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. + * @brief Extracts the physical address from the underlying bitset read from bit index 12 - 51. + * + * @note 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. */ diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index a8cca4c..df232ea 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -44,9 +44,10 @@ namespace teachos::arch::memory::paging auto translate_address(std::size_t virtual_address) -> std::optional; /** - * @brief Maps a virtual page to a physical frame in the page table with the specified flags. Allocates and maps an - * entry in every page level if it does not exists yet down to level 1. If the level 1 page table already exists it - * halts execution instead. + * @brief Maps a virtual page to a physical frame in the page table with the specified flags. + * + * @note Allocates and maps an entry in every page level if it does not exists yet down to level 1. If the level 1 + * page table already exists it halts execution instead. * * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and * deallocate method. @@ -93,6 +94,8 @@ namespace teachos::arch::memory::paging /** * @brief Allocates the next free frame and then uses that frame to call map_page_to_frame. + * + * @see map_page_to_frame */ template auto map_next_free_page_to_frame(T & allocator, virtual_page page, std::bitset<64U> flags) -> void @@ -104,6 +107,8 @@ namespace teachos::arch::memory::paging /** * @brief Gets the corresponding page the given frame has to be contained in and uses that to call map_page_to_frame. + * + * @see map_page_to_frame */ template auto identity_map(T & allocator, allocator::physical_frame frame, std::bitset<64U> flags) -> void @@ -113,8 +118,10 @@ namespace teachos::arch::memory::paging } /** - * @brief Unmaps the virtual page from the previously mapped to physical frame and resets the flags. Deallocates and - * unmaps the entry in every page level if this page was the last one up to level 4. + * @brief Unmaps the virtual page from the previously mapped to physical frame and resets the flags. + * + * @note Deallocates and unmaps the entry in every page level if this page was the last one up to level 4 and ensures + * to clear the Translation Lookaside Buffer, so that the unmapped value is removed from cache as well. * * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and * deallocate method. diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 9aaaafb..feb327a 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -8,9 +8,11 @@ namespace teachos::arch::memory::paging constexpr std::size_t PAGE_TABLE_ENTRY_COUNT = 512U; ///< Default entry count of a page table in x86_84 is 512. /** - * @brief Forward delcaration of the page_table, because it should only be accessible over the handle, the actual - * methods or constructor are not defined meaning they are not callable from outside. Instead the struct is only fully - * defined in the implementation (.cpp) file of the page table, and therefore also only accesible in that file. + * @brief Forward delcaration of the page_table, because it should only be accessible over the handle. + * + * @note The actual methods or constructor are not defined meaning they are not callable from outside. Instead the + * struct is only fully defined in the implementation (.cpp) file of the page table, and therefore the memthods are + * only accesible in that file. */ struct page_table; @@ -48,11 +50,11 @@ namespace teachos::arch::memory::paging auto zero_entries() -> void; /** - * @brief Returns the next page table level from the given page table index. + * @brief Returns the next page table level from the given page table index. Meaning we + * use an index into a Level 4 page table to get the according Level 3 page table. * - * Meaning we use an index into a Level 4 page table to get the according Level 3 page table. If this method is - * called with a Level 1 page table it will instead assert and halt execution, because there is no furthere page - * table and mangeling up and returning the physical address would cause hard to debug issues. + * @note If this method is called with a Level 1 page table it will instead assert and halt execution, because there + * is no furthere page table and mangeling up and returning the physical address would cause hard to debug issues. * * @param table_index Index of this page table in the page table one level lower. */ @@ -67,15 +69,16 @@ namespace teachos::arch::memory::paging auto operator[](std::size_t index) const -> entry; /** - * @brief Decrements the page table handle level enum by one. + * @brief Decrements the page table handle level enum by one, is defined so we can use it as a replacement for an + * int index in a range based for loop. * - * Is defined so we can use it as a replacement for an int index in a range based for loop. Will halt execution if - * called with page_table_handle::LEVEL1, because there is no level below. Has to be defined as either a friend - * function or inline header method, because we define an operator of another type. In this instance friend function - * was choosen, because the struct itself also requires the operator, but declaring before the struct is not - * possible, because the enum is in the struct. This is inpossible because the struct requires the operator declared - * before itself to work, and the operator requires the struct declared before itself to work. Furthermore this - * allows the defintion of the method to be done in the cpp, avoiding includes in the header file. + * @note Will halt execution if called with page_table_handle::LEVEL1, because there is no level below. Has to be + * defined as either a friend function or inline header method, because we define an operator of another type. In + * this instance friend function was choosen, because the struct itself also requires the operator, but declaring + * before the struct is not possible, because the enum is in the struct. This is inpossible because the struct + * requires the operator declared before itself to work, and the operator requires the struct declared before itself + * to work. Furthermore this allows the defintion of the method to be done in the cpp, avoiding includes in the + * header file. * * @param value Value we want to decrement on * @return level New level value decrement by one, meaning the level is also decrement by one Level4 --> Level3, ... diff --git a/arch/x86_64/include/arch/video/vga/text.hpp b/arch/x86_64/include/arch/video/vga/text.hpp index 690f4aa..f200da4 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. }; /** @@ -37,21 +37,21 @@ 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 + blink_or_bright, ///< Make the cell blink or more intense, dependent on the VGA configuration. }; /** * @brief The VGA text mode attribute. * - * In the text mode of VGA, every code point being presented is followed by an attribute description. This allows for - * the modification of how the relevant "cell" is presented. + * @note In the text mode of VGA, every code point being presented is followed by an attribute description. This + * allows for the modification of how the relevant "cell" is presented. * * @see vga::text::foreground_flag * @see vga::text::background_flag */ struct attribute { - color foreground_color : 3; ///< The foreground color of the cell, e.g. the color of the code point + 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. @@ -60,7 +60,7 @@ namespace teachos::arch::video::vga::text static_assert(sizeof(attribute) == 1, "The VGA text mode attribute must fit inside a single byte."); /** - * @brief Commonly used VGA text mode attributes + * @brief Commonly used VGA text mode attributes. */ namespace common_attributes { -- cgit v1.2.3 From 5a2892f65abe13c32bb07de697826f374c1d2b1d Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 22 Oct 2024 07:40:35 +0000 Subject: change table level 4 address --- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index a8cca4c..24d8cde 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -73,12 +73,11 @@ namespace teachos::arch::memory::paging if (!next_handle) { auto allocated_frame = allocator.allocate_frame(); - exception_handling::assert(!allocated_frame.has_value(), "[Page mapper] Unable to allocate frame"); + exception_handling::assert(allocated_frame.has_value(), "[Page mapper] Unable to allocate frame"); current_handle[level_index].set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); // There should now be an entry at the previously not existent index, therefore we can simply access it again. next_handle = current_handle.next_table(page.get_level_index(level)); - exception_handling::assert(!next_handle.has_value(), - "[Page mapper] Unable to create new entry into page table"); + exception_handling::assert(next_handle.has_value(), "[Page mapper] Unable to create new entry into page table"); next_handle.value().zero_entries(); } current_handle = next_handle.value(); -- cgit v1.2.3 From 7d4139b6fa0214604f467a782951cdc0f90e903f Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 22 Oct 2024 08:00:57 +0000 Subject: fix page level -- operator --- arch/x86_64/include/arch/memory/paging/page_table.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index feb327a..e6542a2 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -58,7 +58,7 @@ namespace teachos::arch::memory::paging * * @param table_index Index of this page table in the page table one level lower. */ - auto next_table(std::size_t table_index) const -> std::optional; + auto next_table(std::size_t table_index) -> std::optional; /** * @brief Index operator overload to access specific immutable entry directy. @@ -83,7 +83,7 @@ namespace teachos::arch::memory::paging * @param value Value we want to decrement on * @return level New level value decrement by one, meaning the level is also decrement by one Level4 --> Level3, ... */ - friend auto operator--(level value, int) -> level; + friend auto operator--(level & value, int) -> level; private: page_table * handle; ///< Handle to underlying page table, can never be null (invariant ensured by constructor) -- cgit v1.2.3 From d43f5cb4c13b39b89951434e73078859d121cd4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 22 Oct 2024 08:13:13 +0000 Subject: Implement precrement instead --- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 4 ++-- arch/x86_64/include/arch/memory/paging/page_table.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 173db9b..a2d076a 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -63,7 +63,7 @@ namespace teachos::arch::memory::paging { auto current_handle = create_or_get(); - for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; level--) + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) { auto level_index = page.get_level_index(level); auto next_handle = current_handle.next_table(level_index); @@ -136,7 +136,7 @@ namespace teachos::arch::memory::paging auto current_handle = create_or_get(); - for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; level--) + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) { auto level_index = page.get_level_index(level); auto next_handle = current_handle.next_table(level_index); diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index e6542a2..1fd6f61 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -83,7 +83,7 @@ namespace teachos::arch::memory::paging * @param value Value we want to decrement on * @return level New level value decrement by one, meaning the level is also decrement by one Level4 --> Level3, ... */ - friend auto operator--(level & value, int) -> level; + friend auto operator--(level & value) -> level &; private: page_table * handle; ///< Handle to underlying page table, can never be null (invariant ensured by constructor) -- cgit v1.2.3 From c29d8c3b65f63bfd54031412d9c2975ef7571460 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 22 Oct 2024 08:58:48 +0000 Subject: use actual page_table address --- arch/x86_64/include/arch/boot/pointers.hpp | 3 +++ arch/x86_64/include/arch/memory/paging/page_entry.hpp | 4 ++-- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 2 +- arch/x86_64/include/arch/memory/paging/page_table.hpp | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index 25800f4..37840b6 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -1,11 +1,14 @@ #ifndef TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP #define TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP +#include "arch/memory/paging/page_table.hpp" + #include namespace teachos::arch::boot { extern "C" size_t const multiboot_information_pointer; + extern "C" memory::paging::page_table * page_map_level_4; } // namespace teachos::arch::boot #endif diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index 2b3b3f3..33126f0 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -59,9 +59,9 @@ namespace teachos::arch::memory::paging * to calculate_physical_address() will return the new address and flags instead of the old one. * * @param frame Physical frame that contains the address we want to copy into our underlying std::bitset. - * @param flags Entry flags which will be copied into our underlying std::bitset. + * @param additional_flags Entry flags which will be copied into our underlying std::bitset. */ - auto set_entry(allocator::physical_frame frame, std::bitset<64U> flags) -> void; + auto set_entry(allocator::physical_frame frame, std::bitset<64U> additional_flags) -> void; /** * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 173db9b..358b90c 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -77,7 +77,7 @@ namespace teachos::arch::memory::paging exception_handling::assert(allocated_frame.has_value(), "[Page mapper] Unable to allocate frame"); current_handle[level_index].set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); // There should now be an entry at the previously not existent index, therefore we can simply access it again. - next_handle = current_handle.next_table(page.get_level_index(level)); + next_handle = current_handle.next_table(level_index); exception_handling::assert(next_handle.has_value(), "[Page mapper] Unable to create new entry into page table"); next_handle.value().zero_entries(); } diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index e6542a2..ad5c794 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -66,7 +66,7 @@ namespace teachos::arch::memory::paging * @param index Index of the entry we want to access and only read. * @return Entry at the given table index. */ - auto operator[](std::size_t index) const -> entry; + auto operator[](std::size_t index) -> entry &; /** * @brief Decrements the page table handle level enum by one, is defined so we can use it as a replacement for an -- cgit v1.2.3 From d42ef85dbc3786fb45b8b4625b3f07446f51390d Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 22 Oct 2024 09:19:57 +0000 Subject: add todos --- arch/x86_64/include/arch/memory/paging/page_entry.hpp | 4 ++-- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index 33126f0..73aa554 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -85,8 +85,8 @@ namespace teachos::arch::memory::paging */ auto calculate_physical_address() const -> std::size_t; - std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 9 - 11 and 52 - 62 can be freely - ///< used for additional flags by the operating system. + std::bitset<64U> flags = {}; ///< Underlying bitset used to read the flags from. Bits 9 - 11 and 52 - 62 can be + ///< freely used for additional flags by the operating system. }; } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index cd71c73..4735c13 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -79,6 +79,8 @@ namespace teachos::arch::memory::paging // There should now be an entry at the previously not existent index, therefore we can simply access it again. next_handle = current_handle.next_table(level_index); exception_handling::assert(next_handle.has_value(), "[Page mapper] Unable to create new entry into page table"); + + // TODO: Crashes here! next_handle.value().zero_entries(); } current_handle = next_handle.value(); -- cgit v1.2.3 From ef22c9394534014dbda3e2a070df3d02a9fd041e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 22 Oct 2024 09:22:04 +0000 Subject: Remove default initalization of member variables --- arch/x86_64/include/arch/memory/paging/page_entry.hpp | 4 ++-- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index 73aa554..9ca5469 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -85,8 +85,8 @@ namespace teachos::arch::memory::paging */ auto calculate_physical_address() const -> std::size_t; - std::bitset<64U> flags = {}; ///< Underlying bitset used to read the flags from. Bits 9 - 11 and 52 - 62 can be - ///< freely used for additional flags by the operating system. + std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 9 - 11 and 52 - 62 can be + ///< freely used for additional flags by the operating system. }; } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 4735c13..80f6eb4 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -79,8 +79,7 @@ namespace teachos::arch::memory::paging // There should now be an entry at the previously not existent index, therefore we can simply access it again. next_handle = current_handle.next_table(level_index); exception_handling::assert(next_handle.has_value(), "[Page mapper] Unable to create new entry into page table"); - - // TODO: Crashes here! + // TODO: Crashes when trying to access underlying entries array. next_handle.value().zero_entries(); } current_handle = next_handle.value(); -- cgit v1.2.3 From 61db7fa6097a9e3784f8fb18a8d3de47d7d7c007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 23 Oct 2024 13:28:07 +0000 Subject: Extract next_table_or_create into page_table --- .../include/arch/memory/paging/page_mapper.hpp | 19 +------------ .../include/arch/memory/paging/page_table.hpp | 32 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 18 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 80f6eb4..3590dda 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -65,24 +65,7 @@ namespace teachos::arch::memory::paging for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) { - auto level_index = page.get_level_index(level); - auto next_handle = current_handle.next_table(level_index); - // If the next table method failed then it means that the page level of the frame we want allocate has not yet - // been created itself. So we have to do that before we are able to allocate the wanted frame. This has to be done - // for every level, meaning we potenitally create a level 4, level 3 and level 2 page entry, each pointing to a - // page table one level below. - if (!next_handle) - { - auto allocated_frame = allocator.allocate_frame(); - exception_handling::assert(allocated_frame.has_value(), "[Page mapper] Unable to allocate frame"); - current_handle[level_index].set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); - // There should now be an entry at the previously not existent index, therefore we can simply access it again. - next_handle = current_handle.next_table(level_index); - exception_handling::assert(next_handle.has_value(), "[Page mapper] Unable to create new entry into page table"); - // TODO: Crashes when trying to access underlying entries array. - next_handle.value().zero_entries(); - } - current_handle = next_handle.value(); + current_handle = current_handle.next_table_or_create(allocator, page.get_level_index(level)); } auto level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index eb0b984..8250e30 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -1,6 +1,8 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP +#include "arch/exception_handling/assert.hpp" +#include "arch/memory/allocator/area_frame_allocator.hpp" #include "arch/memory/paging/page_entry.hpp" namespace teachos::arch::memory::paging @@ -60,6 +62,36 @@ namespace teachos::arch::memory::paging */ auto next_table(std::size_t table_index) -> std::optional; + /** + * @brief Call next_table and then checks if the table already exists, if it does not it will use the given + * allocator to get the next free frame and set the entry to that instead. + * + * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate + * entries when a new page table is required. + * @param table_index Index of this page table in the page table one level lower. + */ + template + auto next_table_or_create(T & allocator, std::size_t table_index) -> page_table_handle + { + auto next_handle = next_table(table_index); + // If the next table method failed then it means that the page level of the frame we want allocate has not yet + // been created itself. So we have to do that before we are able to allocate the wanted frame. This has to be done + // for every level, meaning we potenitally create a level 4, level 3 and level 2 page entry, each pointing to a + // page table one level below. + if (!next_handle) + { + auto allocated_frame = allocator.allocate_frame(); + exception_handling::assert(allocated_frame.has_value(), "[Page mapper] Unable to allocate frame"); + this->operator[](table_index).set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); + // There should now be an entry at the previously not existent index, therefore we can simply access it again. + next_handle = next_table(table_index); + exception_handling::assert(next_handle.has_value(), "[Page mapper] Unable to create new entry into page table"); + // TODO: Crashes when trying to access underlying entries array. + next_handle.value().zero_entries(); + } + return next_handle.value(); + } + /** * @brief Index operator overload to access specific immutable entry directy. * -- cgit v1.2.3 From 4c97a4e1e2055ce63a0d16d1e5be880792a5e7eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 23 Oct 2024 15:08:10 +0000 Subject: Replace uint64_t with size_t --- arch/x86_64/include/arch/memory/paging/virtual_page.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index 79801ee..f01073d 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -35,7 +35,7 @@ namespace teachos::arch::memory::paging * * @return Start address of the virtual page. */ - auto start_address() const -> uint64_t; + auto start_address() const -> size_t; /** * @brief Calculates the index into the page table with the given level, which leads to this virtual page. @@ -43,7 +43,7 @@ namespace teachos::arch::memory::paging * @param level Level of the page table we want to calculate the index for. * @return Index into the page table with the given level. */ - auto get_level_index(page_table_handle::level level) const -> uint64_t; + auto get_level_index(page_table_handle::level level) const -> size_t; /** * @brief Defaulted equals operator. -- cgit v1.2.3 From c2c7503fec31c07645fdc087dbf1ef487e90912e Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sat, 26 Oct 2024 07:03:01 +0000 Subject: fix mmap type, adjust linker, use std::array --- arch/x86_64/include/arch/memory/multiboot/memory_map.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp index 1a38a30..858ae52 100644 --- a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp @@ -28,10 +28,10 @@ namespace teachos::arch::memory::multiboot */ struct __attribute__((packed)) memory_area { - uint32_t size; ///< Size of this structure in bytes. uint64_t base_address; ///< Base address the memory region starts at. uint64_t area_length; ///< Size of the memory region, added to base_address results in the final address. memory_area_type type; ///< Specific type of memory the region can contain. + uint32_t zero; ///< }; /** -- cgit v1.2.3 From 873f8c52699c6d4e3d32e5df253ae8ec0266a501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 26 Oct 2024 07:10:37 +0000 Subject: Use alignas instead of reserved keyword --- arch/x86_64/include/arch/memory/multiboot/memory_map.hpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp index 858ae52..e30d2c4 100644 --- a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp @@ -21,17 +21,14 @@ namespace teachos::arch::memory::multiboot /** * @brief Defines an entry in the entries array of the memory_map struct. * - * @note Has to have all padding stripped between the individual values, because the size of the entry needs to be - * exactly 24 bytes and not one byte more. See - * https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Packed-Structures.html for more information on the - * used attribute. + * @note Last value needs to be padded, because the size of the entry needs to be + * exactly 24 bytes and not one byte more. */ - struct __attribute__((packed)) memory_area + struct memory_area { uint64_t base_address; ///< Base address the memory region starts at. uint64_t area_length; ///< Size of the memory region, added to base_address results in the final address. - memory_area_type type; ///< Specific type of memory the region can contain. - uint32_t zero; ///< + alignas(8) memory_area_type type; ///< Specific type of memory the region can contain. }; /** -- cgit v1.2.3 From bca36b0c10fcae447c90e211e83987fea28eecdc Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sat, 26 Oct 2024 08:47:26 +0000 Subject: wip --- arch/x86_64/include/arch/boot/pointers.hpp | 2 ++ arch/x86_64/include/arch/memory/paging/page_table.hpp | 5 +++++ 2 files changed, 7 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index 37840b6..2c42605 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -9,6 +9,8 @@ namespace teachos::arch::boot { extern "C" size_t const multiboot_information_pointer; extern "C" memory::paging::page_table * page_map_level_4; + extern "C" memory::paging::page_table * page_map_level_3; + extern "C" memory::paging::page_table * page_map_level_2; } // namespace teachos::arch::boot #endif diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 8250e30..5a072d0 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -46,6 +46,11 @@ namespace teachos::arch::memory::paging */ page_table_handle(page_table * handle, level handle_level); + /** + * @brief Initializes one page table level 3 entry. + */ + void initialize_page_table(); + /** * @brief Set every entry of the page to unused. */ -- cgit v1.2.3 From 878751001c3de6e7fb24c6212957cd5d753a62d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 26 Oct 2024 08:47:56 +0000 Subject: Commit TLB flush --- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 3590dda..4905e9e 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -9,6 +9,17 @@ namespace teachos::arch::memory::paging { + namespace + { + /** + * @brief Invalidates any translation lookaside buffer (TLB) entries into the page table the given entry is cotained + * in. See https://www.felixcloutier.com/x86/invlpg for more information int he used x86 instruction. + * + * @param entry Any entry into the page table we want to invalidate all cached entries in. + */ + auto invalidate_page_cache(entry * entry) -> void { asm volatile("invlpg (%0)" ::"r"(entry) : "memory"); } + } // namespace + /** * @brief Creates a single instance of the level 4 page table table and returns handle to it or alternatively returns * the previously created handle instead. The instance is owned by this method and is static, meaning it lives on for @@ -135,7 +146,7 @@ namespace teachos::arch::memory::paging exception_handling::assert(level1_frame.has_value(), "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); level1_entry.set_unused(); - // TODO: Flush the translation lookaside buffer to clear the entry from cache as well. (mov cr3, cr3) + invalidate_page_cache(&level1_entry); // TODO: Deallocate and unmap level 1, 2, 3 page table entry if this was the last page in them. // TODO: Fix deallocate because it is not yet implemented. allocator.deallocate_frame(level1_frame.value()); -- cgit v1.2.3 From e56964da2dd54e598d3a7fca20fc0071f32026a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 26 Oct 2024 09:20:53 +0000 Subject: Adjust to toolchain updates --- arch/x86_64/include/arch/boot/pointers.hpp | 2 -- arch/x86_64/include/arch/memory/paging/page_table.hpp | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index 2c42605..37840b6 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -9,8 +9,6 @@ namespace teachos::arch::boot { extern "C" size_t const multiboot_information_pointer; extern "C" memory::paging::page_table * page_map_level_4; - extern "C" memory::paging::page_table * page_map_level_3; - extern "C" memory::paging::page_table * page_map_level_2; } // namespace teachos::arch::boot #endif diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 5a072d0..291ea8d 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -47,9 +47,9 @@ namespace teachos::arch::memory::paging page_table_handle(page_table * handle, level handle_level); /** - * @brief Initializes one page table level 3 entry. + * @brief Initializes one page table level 4 entry. */ - void initialize_page_table(); + void initialize_page_tables(); /** * @brief Set every entry of the page to unused. -- cgit v1.2.3 From f4ab51df7f9ed783dbcfbecffc0a9d919c501135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 26 Oct 2024 11:44:12 +0000 Subject: Write P3 table into P4 table at index 0 --- arch/x86_64/include/arch/memory/paging/page_entry.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index 9ca5469..ba972d6 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -34,6 +34,14 @@ namespace teachos::arch::memory::paging 1UL << 63UL, ///< Page is forbidden from executing code (NXE bit in the EFER register has to be set) }; + /** + * @brief Creates a new entry object from a 64bit address. Should follow the scheme where bit index 12 - 51 are the + * actual address and the other bits are flags. + * + * @param flags Flags that will be passed to underlying std::bitset. + */ + explicit entry(uint64_t flags); + /** * @brief Whether the current page is unused, meaning the underlying std::bitset is 0. * -- cgit v1.2.3 From 6eec9c34a83fc5c0d93bc485c2ee0252824c2201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 26 Oct 2024 11:57:11 +0000 Subject: Fix missing default constructor. --- arch/x86_64/include/arch/memory/paging/page_entry.hpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index ba972d6..bfb0184 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -34,6 +34,11 @@ namespace teachos::arch::memory::paging 1UL << 63UL, ///< Page is forbidden from executing code (NXE bit in the EFER register has to be set) }; + /** + * @brief Defaulted constructor. + */ + entry() = default; + /** * @brief Creates a new entry object from a 64bit address. Should follow the scheme where bit index 12 - 51 are the * actual address and the other bits are flags. -- cgit v1.2.3 From a29e823c6ead21fa7c8f6445411d52f57c4518fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 27 Oct 2024 09:21:25 +0000 Subject: Attempt to start using C++20 algorithm calls. --- .../arch/memory/allocator/area_frame_allocator.hpp | 28 +++----------- .../include/arch/memory/multiboot/memory_map.hpp | 45 +++++++++++++++++++++- 2 files changed, 49 insertions(+), 24 deletions(-) (limited to 'arch/x86_64/include') 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 a1b771e..8e971f0 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 @@ -45,22 +45,6 @@ namespace teachos::arch::memory::allocator */ 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. - * - * @return Iterator pointing to first element of the memory area. - */ - auto begin() -> multiboot::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. - * - * @return Iterator pointing to one past the last element of the memory area. - */ - auto end() -> multiboot::memory_area_iterator; - private: /** * @brief Find the next memory area and write it into current_area. @@ -69,12 +53,12 @@ namespace teachos::arch::memory::allocator physical_frame next_free_frame; ///< The physical_frame after the last allocated one. std::optional current_area; ///< The current memory area. - multiboot::memory_area_iterator area_begin; ///< Pointer to the first element of all memory areas. - multiboot::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. + multiboot::memory_area_container const + memory_areas; ///< All memory areas in custom container allows to use std::ranges + 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::allocator diff --git a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp index e30d2c4..3801e57 100644 --- a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp @@ -48,10 +48,16 @@ namespace teachos::arch::memory::multiboot */ struct memory_area_iterator { + /** + * @brief Defaulted constructor. + */ + memory_area_iterator() = default; + /** * @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 or the + * constructo will halt execution. */ explicit memory_area_iterator(memory_area * p); @@ -80,13 +86,48 @@ namespace teachos::arch::memory::multiboot * @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. + * @return Whether both 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. }; + + /** + * @brief Read-only container for memory areas, that allow to easily use the memory_area_iterator in C++20 ranges + * calls. + */ + struct memory_area_container + { + /** + * @brief Constructor. + * + * @param begin Pointer to the first memory area, will be used to construct the begin iterator. + * @param size Amount of entries in the container we want to construct. + */ + memory_area_container(memory_area * begin, std::size_t size); + + /** + * @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. + * + * @return Iterator pointing to first element of the memory area. + */ + auto begin() const -> 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. + * + * @return Iterator pointing to one past the last element of the memory area. + */ + auto end() const -> memory_area_iterator; + + private: + 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. + }; } // namespace teachos::arch::memory::multiboot #endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP -- cgit v1.2.3 From 3fb2780f665eb3514ef07d2d4a83820653e35b52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 27 Oct 2024 11:20:46 +0000 Subject: Use container and C++20 range algorithms for allocator. --- .../include/arch/memory/multiboot/memory_map.hpp | 113 ++++++++++++++++++--- 1 file changed, 100 insertions(+), 13 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp index 3801e57..f9c902a 100644 --- a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp @@ -3,6 +3,7 @@ #include "info.hpp" #include +#include namespace teachos::arch::memory::multiboot { @@ -44,10 +45,14 @@ namespace teachos::arch::memory::multiboot }; /** - * @brief Iterator for memory areas. + * @brief Random access iterator for memory areas. */ struct memory_area_iterator { + using iterator_category = std::random_access_iterator_tag; ///< Iterator category of this type. + using difference_type = std::ptrdiff_t; ///< Type when diving one instance of this iterator by another. + using value_type = memory_area; ///< Underlying value pointed to by this iterator. + /** * @brief Defaulted constructor. */ @@ -57,30 +62,86 @@ namespace teachos::arch::memory::multiboot * @brief Constructor. * * @param p Underlying address the iterator should point too, ensure to not pass an invalid pointer or the - * constructo will halt execution. + * constructor will halt execution. */ - explicit memory_area_iterator(memory_area * p); + explicit memory_area_iterator(value_type * p); /** * @brief Dereferences the initally given pointer to its value. * * @return Reference to the value. */ - memory_area & operator*() const; + auto operator*() const -> value_type &; + + /** + * @brief Get underlying value, which is the intially passed pointer. + * + * @return Underlying value passed intially. + */ + auto operator->() const -> value_type *; /** * @brief Post increment operator. Returns a copy of the value. * * @return Copy of the incremented underlying address. */ - memory_area_iterator operator++(int); + auto operator++(int) -> memory_area_iterator; /** * @brief Pre increment operator. Returns a reference to the changed value. * * @return Reference to the incremented underlying address. */ - memory_area_iterator & operator++(); + auto operator++() -> memory_area_iterator &; + + /** + * @brief Addition assignment operator. Returns a reference to the changed value. + * + * @param value Value we want to add to the underlying address. + * @return Reference to the changed underlying address. + */ + auto operator+=(difference_type value) -> memory_area_iterator &; + + /** + * @brief Subtraction assignment operator. Returns a reference to the changed value. + * + * @param value Value we want to subtract from the underlying address. + * @return Reference to the changed underlying address. + */ + auto operator-=(difference_type value) -> memory_area_iterator &; + + /** + * @brief Addition operator. Returns the changed value. + * + * @param value Value we want to add to a copy of the underlying address. + * @return Copy of underlying address incremented by the given value. + */ + auto operator+(difference_type value) const -> memory_area_iterator; + + /** + * @brief Subtraction operator. Returns the changed value. + * + * @param value Value we want to subtrcat from a copy of the underlying address. + * @return Copy of underlying address decremented by the given value. + */ + auto operator-(difference_type value) const -> memory_area_iterator; + + /** + * @brief Subtraction operator. Returns the size difference between two iterators. + * + * @param other Other iterator we want to substract the underlying address with ours. + * @return Size difference between the underlying address of this instance and the given iterator. + */ + auto operator-(const memory_area_iterator & other) const -> difference_type; + + /** + * @brief Index operator overload. Returns a reference to the value at the given index. Simply returns the + * dereferenced underlying pointer incremented by the given index. + * + * @param index Index we want to access and get the value from. + * @return Reference to the value at the given index. + */ + auto operator[](difference_type index) const -> value_type &; /** * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators. @@ -88,10 +149,18 @@ namespace teachos::arch::memory::multiboot * @param other Other iterator to compare to. * @return Whether both iterators point to the same underlying address in memory. */ - bool operator==(memory_area_iterator const & other) const = default; + auto operator==(memory_area_iterator const & other) const -> bool = default; + + /** + * @brief Defaulted threeway comparsion operator. Simply compares the memory address of both iterators. + * + * @param other Other iterator to compare to. + * @return Whether the given iterator is smaller or larger than this iterator. + */ + auto operator<=>(memory_area_iterator const & other) const -> std::strong_ordering = default; private: - memory_area * ptr; ///< Underlying address the iterator is currently pointing too. + value_type * ptr; ///< Underlying address the iterator is currently pointing too. }; /** @@ -100,13 +169,16 @@ namespace teachos::arch::memory::multiboot */ struct memory_area_container { + using iterator = memory_area_iterator; ///< Iterators used by this container. + using size_type = std::size_t; ///< Maximum size of this container. + /** * @brief Constructor. * * @param begin Pointer to the first memory area, will be used to construct the begin iterator. * @param size Amount of entries in the container we want to construct. */ - memory_area_container(memory_area * begin, std::size_t size); + memory_area_container(memory_area_iterator::value_type * begin, size_type size); /** * @brief Returns the iterator pointing to the first element of the memory area. @@ -114,7 +186,7 @@ namespace teachos::arch::memory::multiboot * * @return Iterator pointing to first element of the memory area. */ - auto begin() const -> memory_area_iterator; + auto begin() const -> iterator; /** * @brief Returns the iterator pointing to one past the last element of the memory area. @@ -122,11 +194,26 @@ namespace teachos::arch::memory::multiboot * * @return Iterator pointing to one past the last element of the memory area. */ - auto end() const -> memory_area_iterator; + auto end() const -> iterator; + + /** + * @brief Calculates the size of this container, simply subtracts the iterator pointing to the first element by the + * last. + * + * @return Actual size of this container. + */ + auto size() const -> size_type; + + /** + * @brief Calcualtes the size and returns true if the size is 0 and the container therefore emtpy. + * + * @return Whether the container is empty, size being 0 or not + */ + auto empty() const -> bool; private: - 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. + iterator area_begin; ///< Pointer to the first element of all memory areas. + iterator area_end; ///< Pointer to one pas the last element of all memory areas. }; } // namespace teachos::arch::memory::multiboot -- cgit v1.2.3 From becb1ce0abdaf4e6ad08bb6db7c706dd13a1294b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 27 Oct 2024 11:29:36 +0000 Subject: Fix typo --- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 4905e9e..7a8e2c9 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -95,7 +95,7 @@ namespace teachos::arch::memory::paging auto map_next_free_page_to_frame(T & allocator, virtual_page page, std::bitset<64U> flags) -> void { auto frame = allocator.allocate_frame(); - exception_handling::assert(!frame.has_value(), "[Page mapper] Out of memory exception"); + exception_handling::assert(frame.has_value(), "[Page mapper] Out of memory exception"); map_page_to_frame(allocator, page, frame.value(), flags); } -- cgit v1.2.3 From 1518177efac38961a36db0bc40152d00c38e6281 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 27 Oct 2024 13:27:33 +0000 Subject: add correct optional handling --- arch/x86_64/include/arch/memory/paging/page_table.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 291ea8d..8fcde9f 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -83,7 +83,7 @@ namespace teachos::arch::memory::paging // been created itself. So we have to do that before we are able to allocate the wanted frame. This has to be done // for every level, meaning we potenitally create a level 4, level 3 and level 2 page entry, each pointing to a // page table one level below. - if (!next_handle) + if (!next_handle.has_value()) { auto allocated_frame = allocator.allocate_frame(); exception_handling::assert(allocated_frame.has_value(), "[Page mapper] Unable to allocate frame"); -- cgit v1.2.3 From 38e87d52891429d56d20a54ce205d1e421068f36 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 27 Oct 2024 14:16:35 +0000 Subject: update gas --- arch/x86_64/include/arch/memory/paging/page_entry.hpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index bfb0184..5959801 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -68,8 +68,7 @@ namespace teachos::arch::memory::paging auto calculate_pointed_to_frame() const -> std::optional; /** - * @brief Copies the address and flags from the given physical frame into the underlying std::bitset so future calls - * to calculate_physical_address() will return the new address and flags instead of the old one. + * @brief Copies the address and flags from the given physical frame into the underlying std::bitset * * @param frame Physical frame that contains the address we want to copy into our underlying std::bitset. * @param additional_flags Entry flags which will be copied into our underlying std::bitset. @@ -88,16 +87,6 @@ namespace teachos::arch::memory::paging auto contains_flags(std::bitset<64U> other) const -> bool; private: - /** - * @brief Extracts the physical address from the underlying bitset read from bit index 12 - 51. - * - * @note 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; - std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 9 - 11 and 52 - 62 can be ///< freely used for additional flags by the operating system. }; -- cgit v1.2.3 From acbd91c9898808a928af0b1bdd9d5058e8a91f62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 27 Oct 2024 14:55:52 +0000 Subject: Add typedef for virtual / physical addresses --- .../include/arch/memory/allocator/physical_frame.hpp | 6 ++++-- .../include/arch/memory/paging/page_mapper.hpp | 20 ++++++++++---------- .../include/arch/memory/paging/virtual_page.hpp | 6 ++++-- 3 files changed, 18 insertions(+), 14 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp index e33c77a..87c14ac 100644 --- a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp +++ b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp @@ -6,6 +6,8 @@ namespace teachos::arch::memory::allocator { + typedef std::size_t physical_address; + constexpr std::size_t PAGE_FRAME_SIZE = 4096U; ///< Default page size of x86_84 is always 4KiB. /** @@ -24,10 +26,10 @@ namespace teachos::arch::memory::allocator /** * @brief Returns the physical frame the given address is contained in. * - * @param physical_address Physical address we want to get the corresponding physical frame for. + * @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(std::size_t physical_address) -> physical_frame; + auto static containing_address(physical_address address) -> physical_frame; /** * @brief Evaluates the start address of the physical frame. diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 7a8e2c9..5b74bd2 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -30,8 +30,16 @@ namespace teachos::arch::memory::paging auto create_or_get() -> page_table_handle; /** - * @brief Translates page into physical frame, will first attempt to parse normally using default page size and if it - * failed attempt to parse using huge pages. + * @brief Translates virtual address into corresponding physical address. Calls translate_page under the hood. + * + * @param address Virtual address we want to translate into physical one. + * @return Physical address corresponding to the provided virtual address. + */ + auto translate_address(virtual_address address) -> std::optional; + + /** + * @brief Translates page into physical frame, will first attempt to parse normally using default page size and if + * it failed attempt to parse using huge pages. * * @param page Page to translate into physical frame. * @return Physical frame corresponding to the provided virtual page. @@ -46,14 +54,6 @@ namespace teachos::arch::memory::paging */ auto translate_huge_page(virtual_page page) -> std::optional; - /** - * @brief Translate virtual into phyical address. - * - * @param virtual_address Address to translate into physical. - * @return Physical address. - */ - auto translate_address(std::size_t virtual_address) -> std::optional; - /** * @brief Maps a virtual page to a physical frame in the page table with the specified flags. * diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index f01073d..b9e2195 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -10,6 +10,8 @@ namespace teachos::arch::memory::paging { + typedef std::size_t virtual_address; + /** * @brief Virtual page entry contained in P1 page tables */ @@ -25,10 +27,10 @@ namespace teachos::arch::memory::paging /** * @brief Returns the virtual page the given address is contained in. * - * @param virtual_address Virtual address we want to get the corresponding virtual page for. + * @param address Virtual address we want to get the corresponding virtual page for. * @return Frame the given address is contained in. */ - auto static containing_address(std::size_t virtual_address) -> virtual_page; + auto static containing_address(virtual_address address) -> virtual_page; /** * @brief Evaluates the start address of the virtual page. -- cgit v1.2.3 From 58d01f6aae80a66faa5163602c399c28dcf30cb6 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 27 Oct 2024 15:25:57 +0000 Subject: revert p4 address update --- arch/x86_64/include/arch/boot/pointers.hpp | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index 37840b6..18c41ce 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -8,7 +8,6 @@ namespace teachos::arch::boot { extern "C" size_t const multiboot_information_pointer; - extern "C" memory::paging::page_table * page_map_level_4; } // namespace teachos::arch::boot #endif -- cgit v1.2.3 From 04b0285d8329e45cea426aa1a8e69203685a4467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 28 Oct 2024 10:15:18 +0000 Subject: Move iterator and container into generic template classes. Use algorithms instead of raw pointer for loops --- .../arch/memory/multiboot/elf_symbols_section.hpp | 7 +- .../include/arch/memory/multiboot/memory_map.hpp | 178 +-------------------- .../include/arch/memory/multiboot/reader.hpp | 9 +- arch/x86_64/include/arch/shared/container.hpp | 73 +++++++++ .../include/arch/shared/random_access_iterator.hpp | 167 +++++++++++++++++++ 5 files changed, 256 insertions(+), 178 deletions(-) create mode 100644 arch/x86_64/include/arch/shared/container.hpp create mode 100644 arch/x86_64/include/arch/shared/random_access_iterator.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp index fc8cb15..c9989ae 100644 --- a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp @@ -1,7 +1,10 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP #define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP -#include "info.hpp" +#include "arch/memory/multiboot/info.hpp" +#include "arch/shared/container.hpp" +#include "arch/shared/random_access_iterator.hpp" + #include #include @@ -158,6 +161,8 @@ namespace teachos::arch::memory::multiboot std::byte end; ///< Marks the end of the tag, used to mark the beginning of any additional data. ///< contained in the section, to ensure byte alignment is actually 4 byte. }; + + typedef shared::container> elf_section_header_container; } // namespace teachos::arch::memory::multiboot #endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp index f9c902a..910eecb 100644 --- a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp @@ -1,9 +1,11 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP #define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP -#include "info.hpp" +#include "arch/memory/multiboot/info.hpp" +#include "arch/shared/container.hpp" +#include "arch/shared/random_access_iterator.hpp" + #include -#include namespace teachos::arch::memory::multiboot { @@ -44,177 +46,7 @@ namespace teachos::arch::memory::multiboot struct memory_area entries; ///< Specific memory regions. }; - /** - * @brief Random access iterator for memory areas. - */ - struct memory_area_iterator - { - using iterator_category = std::random_access_iterator_tag; ///< Iterator category of this type. - using difference_type = std::ptrdiff_t; ///< Type when diving one instance of this iterator by another. - using value_type = memory_area; ///< Underlying value pointed to by this iterator. - - /** - * @brief Defaulted constructor. - */ - memory_area_iterator() = default; - - /** - * @brief Constructor. - * - * @param p Underlying address the iterator should point too, ensure to not pass an invalid pointer or the - * constructor will halt execution. - */ - explicit memory_area_iterator(value_type * p); - - /** - * @brief Dereferences the initally given pointer to its value. - * - * @return Reference to the value. - */ - auto operator*() const -> value_type &; - - /** - * @brief Get underlying value, which is the intially passed pointer. - * - * @return Underlying value passed intially. - */ - auto operator->() const -> value_type *; - - /** - * @brief Post increment operator. Returns a copy of the value. - * - * @return Copy of the incremented underlying address. - */ - auto operator++(int) -> memory_area_iterator; - - /** - * @brief Pre increment operator. Returns a reference to the changed value. - * - * @return Reference to the incremented underlying address. - */ - auto operator++() -> memory_area_iterator &; - - /** - * @brief Addition assignment operator. Returns a reference to the changed value. - * - * @param value Value we want to add to the underlying address. - * @return Reference to the changed underlying address. - */ - auto operator+=(difference_type value) -> memory_area_iterator &; - - /** - * @brief Subtraction assignment operator. Returns a reference to the changed value. - * - * @param value Value we want to subtract from the underlying address. - * @return Reference to the changed underlying address. - */ - auto operator-=(difference_type value) -> memory_area_iterator &; - - /** - * @brief Addition operator. Returns the changed value. - * - * @param value Value we want to add to a copy of the underlying address. - * @return Copy of underlying address incremented by the given value. - */ - auto operator+(difference_type value) const -> memory_area_iterator; - - /** - * @brief Subtraction operator. Returns the changed value. - * - * @param value Value we want to subtrcat from a copy of the underlying address. - * @return Copy of underlying address decremented by the given value. - */ - auto operator-(difference_type value) const -> memory_area_iterator; - - /** - * @brief Subtraction operator. Returns the size difference between two iterators. - * - * @param other Other iterator we want to substract the underlying address with ours. - * @return Size difference between the underlying address of this instance and the given iterator. - */ - auto operator-(const memory_area_iterator & other) const -> difference_type; - - /** - * @brief Index operator overload. Returns a reference to the value at the given index. Simply returns the - * dereferenced underlying pointer incremented by the given index. - * - * @param index Index we want to access and get the value from. - * @return Reference to the value at the given index. - */ - auto operator[](difference_type index) const -> value_type &; - - /** - * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators. - * - * @param other Other iterator to compare to. - * @return Whether both iterators point to the same underlying address in memory. - */ - auto operator==(memory_area_iterator const & other) const -> bool = default; - - /** - * @brief Defaulted threeway comparsion operator. Simply compares the memory address of both iterators. - * - * @param other Other iterator to compare to. - * @return Whether the given iterator is smaller or larger than this iterator. - */ - auto operator<=>(memory_area_iterator const & other) const -> std::strong_ordering = default; - - private: - value_type * ptr; ///< Underlying address the iterator is currently pointing too. - }; - - /** - * @brief Read-only container for memory areas, that allow to easily use the memory_area_iterator in C++20 ranges - * calls. - */ - struct memory_area_container - { - using iterator = memory_area_iterator; ///< Iterators used by this container. - using size_type = std::size_t; ///< Maximum size of this container. - - /** - * @brief Constructor. - * - * @param begin Pointer to the first memory area, will be used to construct the begin iterator. - * @param size Amount of entries in the container we want to construct. - */ - memory_area_container(memory_area_iterator::value_type * begin, size_type size); - - /** - * @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. - * - * @return Iterator pointing to first element of the memory area. - */ - auto begin() const -> 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. - * - * @return Iterator pointing to one past the last element of the memory area. - */ - auto end() const -> iterator; - - /** - * @brief Calculates the size of this container, simply subtracts the iterator pointing to the first element by the - * last. - * - * @return Actual size of this container. - */ - auto size() const -> size_type; - - /** - * @brief Calcualtes the size and returns true if the size is 0 and the container therefore emtpy. - * - * @return Whether the container is empty, size being 0 or not - */ - auto empty() const -> bool; - - private: - iterator area_begin; ///< Pointer to the first element of all memory areas. - iterator area_end; ///< Pointer to one pas the last element of all memory areas. - }; + typedef shared::container> memory_area_container; } // namespace teachos::arch::memory::multiboot #endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/reader.hpp b/arch/x86_64/include/arch/memory/multiboot/reader.hpp index 393db8b..baa49c9 100644 --- a/arch/x86_64/include/arch/memory/multiboot/reader.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/reader.hpp @@ -1,8 +1,8 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP #define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP -#include "elf_symbols_section.hpp" -#include "memory_map.hpp" +#include "arch/memory/multiboot/memory_map.hpp" + #include namespace teachos::arch::memory::multiboot @@ -17,8 +17,9 @@ namespace teachos::arch::memory::multiboot std::size_t kernel_end; ///< End address of the kernel code in memory. std::size_t multiboot_start; ///< Start address of the multiboot code in memory. std::size_t multiboot_end; ///< End address of the multiboot code in memory. - memory_area * memory_areas; ///< Non-owning pointer to the first element of all memory areas. - uint8_t area_count; ///< Amount of total entries in the memory_areas array. + memory_area_container::iterator + begin_area; ///< Iterator containing non-owning pointer to the first element of all memory areas. + memory_area_container::iterator end_area; ///< Iterator pointing to one past the last element of all memory areas. }; /** diff --git a/arch/x86_64/include/arch/shared/container.hpp b/arch/x86_64/include/arch/shared/container.hpp new file mode 100644 index 0000000..8ea0d08 --- /dev/null +++ b/arch/x86_64/include/arch/shared/container.hpp @@ -0,0 +1,73 @@ +#ifndef TEACHOS_ARCH_X86_64_SHARED_CONTAINER_HPP +#define TEACHOS_ARCH_X86_64_SHARED_CONTAINER_HPP + +#include "arch/exception_handling/assert.hpp" + +#include + +namespace teachos::arch::shared +{ + /** + * @brief Read-only container for given template type, that allow to easily use this container instance in C++20 + * ranges calls. + * + * @tparam T Iterator the container uses to signal the start and end of it's data. + */ + template + struct container + { + using iterator = T; ///< Iterators used by this container. + using size_type = std::size_t; ///< Maximum size of this container. + + /** + * @brief Constructor. + * + * @param begin Iterator containing non-owning pointer to the first element of all memory areas. + * @param end Iterator pointing to one past the last element of all memory areas. + */ + container(iterator begin, iterator end) + : begin_itr(begin) + , end_itr(end) + { + exception_handling::assert(begin != iterator{}, "[Memory Area] Attempted to pass nullptr as begin iterator"); + exception_handling::assert(end != iterator{}, "[Memory Area] Attempted to pass nullptr as end iterator"); + } + + /** + * @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. + * + * @return Iterator pointing to first element of the memory area. + */ + auto begin() const -> iterator { return begin_itr; } + + /** + * @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. + * + * @return Iterator pointing to one past the last element of the memory area. + */ + auto end() const -> iterator { return end_itr; } + + /** + * @brief Calculates the size of this container, simply subtracts the iterator pointing to the first element by the + * last. + * + * @return Actual size of this container. + */ + auto size() const -> size_type { return std::distance(begin(), end()); } + + /** + * @brief Calcualtes the size and returns true if the size is 0 and the container therefore emtpy. + * + * @return Whether the container is empty, size being 0 or not + */ + auto empty() const -> bool { return size() == 0; } + + private: + iterator begin_itr; ///< Pointer to the first element of the given template type. + iterator end_itr; ///< Pointer to one pas the last element of the given template type. + }; +} // namespace teachos::arch::shared + +#endif // TEACHOS_ARCH_X86_64_SHARED_CONTAINER_HPP diff --git a/arch/x86_64/include/arch/shared/random_access_iterator.hpp b/arch/x86_64/include/arch/shared/random_access_iterator.hpp new file mode 100644 index 0000000..392b925 --- /dev/null +++ b/arch/x86_64/include/arch/shared/random_access_iterator.hpp @@ -0,0 +1,167 @@ +#ifndef TEACHOS_ARCH_X86_64_SHARED_RANDOM_ACCESS_ITERATOR_HPP +#define TEACHOS_ARCH_X86_64_SHARED_RANDOM_ACCESS_ITERATOR_HPP + +#include + +namespace teachos::arch::shared +{ + /** + * @brief Generic random access iterator for given template type. Can be a nullptr, ensure to check when using this + * iterator. Allows to easily use this iterator instance in algorithm calls. + * + * @tparam T Value the iterator points too. + */ + template + struct random_access_iterator + { + using iterator_category = std::random_access_iterator_tag; ///< Iterator category of this type. + using difference_type = std::ptrdiff_t; ///< Type when diving one instance of this iterator by another. + using value_type = T; ///< Underlying value pointed to by this iterator. + + /** + * @brief Defaulted constructor. + */ + random_access_iterator() = default; + + /** + * @brief Constructor. + * + * @param p Underlying address the iterator should point too, ensure to not pass an invalid pointer or the + * constructor will halt execution. + */ + explicit random_access_iterator(value_type * p) + : ptr(p) + { + // Nothing to do + } + + /** + * @brief Dereferences the initally given pointer to its value. + * + * @return Reference to the value. + */ + auto operator*() const -> value_type & { return *ptr; } + + /** + * @brief Get underlying value, which is the intially passed pointer. + * + * @return Underlying value passed intially. + */ + auto operator->() const -> value_type * { return ptr; } + + /** + * @brief Post increment operator. Returns a copy of the value. + * + * @return Copy of the incremented underlying address. + */ + auto operator++(int) -> random_access_iterator + { + random_access_iterator old_value = *this; + ++ptr; + return old_value; + } + + /** + * @brief Pre increment operator. Returns a reference to the changed value. + * + * @return Reference to the incremented underlying address. + */ + auto operator++() -> random_access_iterator & + { + ++ptr; + return *this; + } + + /** + * @brief Addition assignment operator. Returns a reference to the changed value. + * + * @param value Value we want to add to the underlying address. + * @return Reference to the changed underlying address. + */ + auto operator+=(difference_type value) -> random_access_iterator & + { + ptr += value; + return *this; + } + + /** + * @brief Subtraction assignment operator. Returns a reference to the changed value. + * + * @param value Value we want to subtract from the underlying address. + * @return Reference to the changed underlying address. + */ + auto operator-=(difference_type value) -> random_access_iterator & + { + ptr -= value; + return *this; + } + + /** + * @brief Addition operator. Returns the changed value. + * + * @param value Value we want to add to a copy of the underlying address. + * @return Copy of underlying address incremented by the given value. + */ + auto operator+(difference_type value) const -> random_access_iterator + { + return random_access_iterator{ptr + value}; + } + + /** + * @brief Subtraction operator. Returns the changed value. + * + * @param value Value we want to subtrcat from a copy of the underlying address. + * @return Copy of underlying address decremented by the given value. + */ + auto operator-(difference_type value) const -> random_access_iterator + { + return random_access_iterator{ptr - value}; + } + + /** + * @brief Subtraction operator. Returns the size difference between two iterators. + * + * @param other Other iterator we want to substract the underlying address with ours. + * @return Size difference between the underlying address of this instance and the given iterator. + */ + auto operator-(const random_access_iterator & other) const -> difference_type { return ptr - other.ptr; } + + /** + * @brief Index operator overload. Returns a reference to the value at the given index. Simply returns the + * dereferenced underlying pointer incremented by the given index. + * + * @param index Index we want to access and get the value from. + * @return Reference to the value at the given index. + */ + auto operator[](difference_type index) const -> value_type & { return *(ptr + index); } + + /** + * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators. + * + * @param other Other iterator to compare to. + * @return Whether both iterators point to the same underlying address in memory. + */ + auto operator==(random_access_iterator const & other) const -> bool = default; + + /** + * @brief Defaulted negated comparsion operator. Simply compares the memory address of both iterators. + * + * @param other Other iterator to compare to. + * @return Whether both iterators don't point to the same underlying address in memory. + */ + auto operator!=(random_access_iterator const & other) const -> bool = default; + + /** + * @brief Defaulted threeway comparsion operator. Simply compares the memory address of both iterators. + * + * @param other Other iterator to compare to. + * @return Whether the given iterator is smaller or larger than this iterator. + */ + auto operator<=>(random_access_iterator const & other) const -> std::strong_ordering = default; + + private: + value_type * ptr = {}; ///< Underlying address the iterator is currently pointing too. + }; +} // namespace teachos::arch::shared + +#endif // TEACHOS_ARCH_X86_64_SHARED_RANDOM_ACCESS_ITERATOR_HPP -- cgit v1.2.3 From 58680f7d84ca5771be31c0037e8caf5791d79b3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 28 Oct 2024 12:29:39 +0000 Subject: Fix invalid assertion --- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 2 +- arch/x86_64/include/arch/memory/paging/page_table.hpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 5b74bd2..c07c73c 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -82,7 +82,7 @@ namespace teachos::arch::memory::paging auto level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE), "[Page Mapper] Unable to map huge pages"); - arch::exception_handling::assert(!level1_entry.is_unused(), "[Page Mapper] Page table entry is already used"); + arch::exception_handling::assert(level1_entry.is_unused(), "[Page Mapper] Page table entry is already used"); level1_entry.set_entry(frame, flags | std::bitset<64U>{entry::PRESENT}); } diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 8fcde9f..765e9bb 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -91,7 +91,6 @@ namespace teachos::arch::memory::paging // There should now be an entry at the previously not existent index, therefore we can simply access it again. next_handle = next_table(table_index); exception_handling::assert(next_handle.has_value(), "[Page mapper] Unable to create new entry into page table"); - // TODO: Crashes when trying to access underlying entries array. next_handle.value().zero_entries(); } return next_handle.value(); -- cgit v1.2.3 From efcb913196ccf0386a557e8c1053c430e5896179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 28 Oct 2024 12:45:46 +0000 Subject: Convert bitset to uint64_t instead of uint64_t to bitset --- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index c07c73c..e08f195 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -83,7 +83,7 @@ namespace teachos::arch::memory::paging arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE), "[Page Mapper] Unable to map huge pages"); arch::exception_handling::assert(level1_entry.is_unused(), "[Page Mapper] Page table entry is already used"); - level1_entry.set_entry(frame, flags | std::bitset<64U>{entry::PRESENT}); + level1_entry.set_entry(frame, flags.to_ulong() | entry::PRESENT); } /** -- cgit v1.2.3 From e5925df93411429340d2887594004aaa690d2ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 28 Oct 2024 13:32:09 +0000 Subject: Adjust constant and make all possible variables const --- arch/x86_64/include/arch/memory/allocator/physical_frame.hpp | 6 +++--- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 10 +++++----- arch/x86_64/include/arch/memory/paging/page_table.hpp | 4 ++-- arch/x86_64/include/arch/memory/paging/virtual_page.hpp | 4 ++-- arch/x86_64/include/arch/shared/random_access_iterator.hpp | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp index 87c14ac..39406af 100644 --- a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp +++ b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp @@ -8,7 +8,7 @@ namespace teachos::arch::memory::allocator { typedef std::size_t physical_address; - constexpr std::size_t PAGE_FRAME_SIZE = 4096U; ///< Default page size of x86_84 is always 4KiB. + 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 @@ -41,12 +41,12 @@ namespace teachos::arch::memory::allocator /** * @brief Defaulted equals operator. */ - constexpr auto operator==(const physical_frame & other) const -> bool = default; + auto operator==(const physical_frame & other) const -> bool = default; /** * @brief Defaulted three-way comparsion operator. */ - constexpr auto operator<=>(const physical_frame & other) const -> std::partial_ordering = default; + auto operator<=>(const physical_frame & 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. diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index e08f195..4edcea9 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -94,7 +94,7 @@ namespace teachos::arch::memory::paging template auto map_next_free_page_to_frame(T & allocator, virtual_page page, std::bitset<64U> flags) -> void { - auto frame = allocator.allocate_frame(); + auto const frame = allocator.allocate_frame(); exception_handling::assert(frame.has_value(), "[Page mapper] Out of memory exception"); map_page_to_frame(allocator, page, frame.value(), flags); } @@ -107,7 +107,7 @@ namespace teachos::arch::memory::paging template auto identity_map(T & allocator, allocator::physical_frame frame, std::bitset<64U> flags) -> void { - auto page = virtual_page::containing_address(frame.start_address()); + auto const page = virtual_page::containing_address(frame.start_address()); map_page_to_frame(allocator, page, frame, flags); } @@ -133,8 +133,8 @@ namespace teachos::arch::memory::paging for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) { - auto level_index = page.get_level_index(level); - auto next_handle = current_handle.next_table(level_index); + auto const level_index = page.get_level_index(level); + auto const next_handle = current_handle.next_table(level_index); // The next table method failed even tough the page has to be mapped already, because translate_page did not fail. // This can only mean that we attempted to unmap a huge page, which is not supported in the first place. exception_handling::assert(next_handle.has_value(), "[Page Mapper] Unable to unmap huge pages"); @@ -142,7 +142,7 @@ namespace teachos::arch::memory::paging } auto level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; - auto level1_frame = level1_entry.calculate_pointed_to_frame(); + auto const level1_frame = level1_entry.calculate_pointed_to_frame(); exception_handling::assert(level1_frame.has_value(), "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); level1_entry.set_unused(); diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 765e9bb..e4847e3 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -7,7 +7,7 @@ namespace teachos::arch::memory::paging { - constexpr std::size_t PAGE_TABLE_ENTRY_COUNT = 512U; ///< Default entry count of a page table in x86_84 is 512. + std::size_t constexpr PAGE_TABLE_ENTRY_COUNT = 512U; ///< Default entry count of a page table in x86_84 is 512. /** * @brief Forward delcaration of the page_table, because it should only be accessible over the handle. @@ -85,7 +85,7 @@ namespace teachos::arch::memory::paging // page table one level below. if (!next_handle.has_value()) { - auto allocated_frame = allocator.allocate_frame(); + auto const allocated_frame = allocator.allocate_frame(); exception_handling::assert(allocated_frame.has_value(), "[Page mapper] Unable to allocate frame"); this->operator[](table_index).set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); // There should now be an entry at the previously not existent index, therefore we can simply access it again. diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index b9e2195..934ecf2 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -50,12 +50,12 @@ namespace teachos::arch::memory::paging /** * @brief Defaulted equals operator. */ - constexpr auto operator==(const virtual_page & other) const -> bool = default; + 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; + auto operator<=>(const virtual_page & other) const -> std::partial_ordering = default; std::size_t page_number; ///< Index number of the current virtual page, used to distinguish it from other pages. }; diff --git a/arch/x86_64/include/arch/shared/random_access_iterator.hpp b/arch/x86_64/include/arch/shared/random_access_iterator.hpp index 392b925..13deb68 100644 --- a/arch/x86_64/include/arch/shared/random_access_iterator.hpp +++ b/arch/x86_64/include/arch/shared/random_access_iterator.hpp @@ -56,7 +56,7 @@ namespace teachos::arch::shared */ auto operator++(int) -> random_access_iterator { - random_access_iterator old_value = *this; + random_access_iterator const old_value = *this; ++ptr; return old_value; } -- cgit v1.2.3 From aa981cad951c4aa2a5e2f7a7f8f1b7b9a0ff4bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 28 Oct 2024 14:41:31 +0000 Subject: Fix lost updates, because of writing into copies instead of references --- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 4edcea9..d852fbc 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -79,7 +79,7 @@ namespace teachos::arch::memory::paging current_handle = current_handle.next_table_or_create(allocator, page.get_level_index(level)); } - auto level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; + auto & level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE), "[Page Mapper] Unable to map huge pages"); arch::exception_handling::assert(level1_entry.is_unused(), "[Page Mapper] Page table entry is already used"); @@ -141,7 +141,7 @@ namespace teachos::arch::memory::paging current_handle = next_handle.value(); } - auto level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; + auto & level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; auto const level1_frame = level1_entry.calculate_pointed_to_frame(); exception_handling::assert(level1_frame.has_value(), "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); -- cgit v1.2.3 From bd3ae51093b504bd035cb698c637ef6f82994ba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 28 Oct 2024 14:48:32 +0000 Subject: Remove not required includes --- arch/x86_64/include/arch/boot/pointers.hpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index 18c41ce..25800f4 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -1,8 +1,6 @@ #ifndef TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP #define TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP -#include "arch/memory/paging/page_table.hpp" - #include namespace teachos::arch::boot -- cgit v1.2.3 From f9f047f519d0100c40b914d3ce777ac2f8430b38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 28 Oct 2024 15:18:31 +0000 Subject: Add is empty check method for page table --- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 2 +- arch/x86_64/include/arch/memory/paging/page_table.hpp | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index d852fbc..6a0c989 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -146,10 +146,10 @@ namespace teachos::arch::memory::paging exception_handling::assert(level1_frame.has_value(), "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); level1_entry.set_unused(); - invalidate_page_cache(&level1_entry); // TODO: Deallocate and unmap level 1, 2, 3 page table entry if this was the last page in them. // TODO: Fix deallocate because it is not yet implemented. allocator.deallocate_frame(level1_frame.value()); + invalidate_page_cache(&level1_entry); } } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index e4847e3..07e7e22 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -56,6 +56,11 @@ namespace teachos::arch::memory::paging */ auto zero_entries() -> void; + /** + * @brief Checks if all entries of this page are unused. + */ + auto is_empty() const -> bool; + /** * @brief Returns the next page table level from the given page table index. Meaning we * use an index into a Level 4 page table to get the according Level 3 page table. @@ -97,13 +102,21 @@ namespace teachos::arch::memory::paging } /** - * @brief Index operator overload to access specific immutable entry directy. + * @brief Index operator overload to access specific mutable entry directy. * * @param index Index of the entry we want to access and only read. * @return Entry at the given table index. */ auto operator[](std::size_t index) -> entry &; + /** + * @brief Index operator overload to access specific immutable entry directy. + * + * @param index Index of the entry we want to access and read or write. + * @return Entry at the given table index. + */ + auto operator[](std::size_t index) const -> entry const &; + /** * @brief Decrements the page table handle level enum by one, is defined so we can use it as a replacement for an * int index in a range based for loop. -- cgit v1.2.3 From 0d16592c8dce876d8e621c73dea41c33339f3173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 29 Oct 2024 06:55:36 +0000 Subject: Use more virtual and physical address typedef where useful --- .../include/arch/memory/allocator/physical_frame.hpp | 2 +- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 14 +++++++++----- arch/x86_64/include/arch/memory/paging/virtual_page.hpp | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp index 39406af..146e557 100644 --- a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp +++ b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp @@ -36,7 +36,7 @@ namespace teachos::arch::memory::allocator * * @return Start address of the physical frame. */ - auto start_address() const -> uint64_t; + auto start_address() const -> physical_address; /** * @brief Defaulted equals operator. diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 6a0c989..0ef552a 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -12,12 +12,16 @@ namespace teachos::arch::memory::paging namespace { /** - * @brief Invalidates any translation lookaside buffer (TLB) entries into the page table the given entry is cotained - * in. See https://www.felixcloutier.com/x86/invlpg for more information int he used x86 instruction. + * @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained + * in. See https://www.felixcloutier.com/x86/invlpg for more information on the used x86 instruction. * - * @param entry Any entry into the page table we want to invalidate all cached entries in. + * @param address Memory address, which will be used to determine the contained page and flush the TLB entry for + * that page. */ - auto invalidate_page_cache(entry * entry) -> void { asm volatile("invlpg (%0)" ::"r"(entry) : "memory"); } + auto invalidate_page_cache(virtual_address address) -> void + { + asm volatile("invlpg (%0)" ::"r"(address) : "memory"); + } } // namespace /** @@ -149,7 +153,7 @@ namespace teachos::arch::memory::paging // TODO: Deallocate and unmap level 1, 2, 3 page table entry if this was the last page in them. // TODO: Fix deallocate because it is not yet implemented. allocator.deallocate_frame(level1_frame.value()); - invalidate_page_cache(&level1_entry); + invalidate_page_cache(page.start_address()); } } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index 934ecf2..8c5613d 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -37,7 +37,7 @@ namespace teachos::arch::memory::paging * * @return Start address of the virtual page. */ - auto start_address() const -> size_t; + auto start_address() const -> virtual_address; /** * @brief Calculates the index into the page table with the given level, which leads to this virtual page. -- cgit v1.2.3 From 4c4479a4b728fd7eaf007649e946f9435ee1e402 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 29 Oct 2024 07:32:24 +0000 Subject: implement page_table unmapping --- .../include/arch/memory/paging/page_mapper.hpp | 41 +++++++++++++++++----- .../include/arch/memory/paging/page_table.hpp | 7 ++++ 2 files changed, 40 insertions(+), 8 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 0ef552a..801ccfb 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -5,6 +5,8 @@ #include "arch/memory/allocator/area_frame_allocator.hpp" #include "arch/memory/paging/virtual_page.hpp" +#include +#include #include namespace teachos::arch::memory::paging @@ -22,6 +24,28 @@ namespace teachos::arch::memory::paging { asm volatile("invlpg (%0)" ::"r"(address) : "memory"); } + + /** + * @brief Unmaps specific page at the current internal handle level. + * + * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and + * deallocate method. + * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate + * entries *when a new page table is required. + * @param page Virtual page that is being unmapped. + * @param handle Page Table handle we want to access the entry that should be cleared on. + */ + template + auto unmap_page_table_entry(T & allocator, virtual_page page, page_table_handle & handle) -> void + { + auto level_index = page.get_level_index(handle.get_level()); + auto & entry = handle[level_index]; + auto const frame = entry.calculate_pointed_to_frame(); + exception_handling::assert(frame.has_value(), + "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); + entry.set_unused(); + allocator.deallocate_frame(frame.value()); + } } // namespace /** @@ -135,8 +159,12 @@ namespace teachos::arch::memory::paging auto current_handle = create_or_get(); + std::array handles{}; + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) { + handles[level] = *current_handle; + auto const level_index = page.get_level_index(level); auto const next_handle = current_handle.next_table(level_index); // The next table method failed even tough the page has to be mapped already, because translate_page did not fail. @@ -145,14 +173,11 @@ namespace teachos::arch::memory::paging current_handle = next_handle.value(); } - auto & level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; - auto const level1_frame = level1_entry.calculate_pointed_to_frame(); - exception_handling::assert(level1_frame.has_value(), - "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); - level1_entry.set_unused(); - // TODO: Deallocate and unmap level 1, 2, 3 page table entry if this was the last page in them. - // TODO: Fix deallocate because it is not yet implemented. - allocator.deallocate_frame(level1_frame.value()); + std::ranges::for_each(handles, [&allocator, page](page_table_handle * handle) { + exception_handling::assert(handle != nullptr, "[Page Mapper] Attempted to unmap page behind nullpointer"); + unmap_page_table_entry(allocator, page, *handle); + }); + invalidate_page_cache(page.start_address()); } } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 07e7e22..02ed099 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -61,6 +61,13 @@ namespace teachos::arch::memory::paging */ auto is_empty() const -> bool; + /** + * @brief Get the current handle level. + * + * @return Current handle level. + */ + auto get_level() const -> level; + /** * @brief Returns the next page table level from the given page table index. Meaning we * use an index into a Level 4 page table to get the according Level 3 page table. -- cgit v1.2.3 From 5334a63e7fc3959536f4f443c86f8913f7cb2451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 29 Oct 2024 08:05:22 +0000 Subject: Unmap all empty page tables in unmap function. --- .../arch/memory/allocator/area_frame_allocator.hpp | 4 ++++ .../include/arch/memory/paging/page_mapper.hpp | 26 ++++++++++++++-------- 2 files changed, 21 insertions(+), 9 deletions(-) (limited to 'arch/x86_64/include') 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 8e971f0..599723f 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 @@ -41,6 +41,10 @@ namespace teachos::arch::memory::allocator /** * @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 ben alocated in the first place. + * * @param physical_frame Previously allocated physical_frame that should be allocated. */ auto deallocate_frame(physical_frame physical_frame) -> void; diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 801ccfb..a9f8eb8 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -158,26 +158,34 @@ namespace teachos::arch::memory::paging "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); auto current_handle = create_or_get(); - - std::array handles{}; + std::array handles{current_handle, current_handle, current_handle, current_handle}; for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) { - handles[level] = *current_handle; - auto const level_index = page.get_level_index(level); auto const next_handle = current_handle.next_table(level_index); // The next table method failed even tough the page has to be mapped already, because translate_page did not fail. // This can only mean that we attempted to unmap a huge page, which is not supported in the first place. exception_handling::assert(next_handle.has_value(), "[Page Mapper] Unable to unmap huge pages"); current_handle = next_handle.value(); + // The level is used as the index, because it ensures the first level is the lowest one and then the remaining + // levels in ascending order. This is required, because we first have to clear the Level 1 page entry to check if + // the Level 1 page is now empty, to clear the Level 2 page entry, which will then also check if the Level 2 page + // is empty and clear the Level 3 page entry and so on. + handles.at(level - 1U) = current_handle; } - std::ranges::for_each(handles, [&allocator, page](page_table_handle * handle) { - exception_handling::assert(handle != nullptr, "[Page Mapper] Attempted to unmap page behind nullpointer"); - unmap_page_table_entry(allocator, page, *handle); - }); - + // Unmaps all entries starting from the Level 1 page table, and unmaps higher levels as well if that entry was the + // last one. We check if it was the last one using is empty on the page table handle, when we have removed the page + // to be unmapped. + for (auto & handle : handles) + { + unmap_page_table_entry(allocator, page, handle); + if (!handle.is_empty()) + { + break; + } + } invalidate_page_cache(page.start_address()); } } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 4e9338075cf30702b922e5aecbc33c18bfd3f759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 29 Oct 2024 08:11:13 +0000 Subject: Remove not required methods --- arch/x86_64/include/arch/memory/paging/page_table.hpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 02ed099..31fb58c 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -46,11 +46,6 @@ namespace teachos::arch::memory::paging */ page_table_handle(page_table * handle, level handle_level); - /** - * @brief Initializes one page table level 4 entry. - */ - void initialize_page_tables(); - /** * @brief Set every entry of the page to unused. */ -- cgit v1.2.3 From dfb0ea2fd7525dd12addf295aef4d642e93ea22a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 29 Oct 2024 09:31:36 +0000 Subject: Create tiny frame allocator which holds only 3 frames --- .../arch/memory/allocator/area_frame_allocator.hpp | 8 ++-- .../arch/memory/allocator/tiny_frame_allocator.hpp | 44 ++++++++++++++++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp (limited to 'arch/x86_64/include') 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 599723f..6135184 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 @@ -27,7 +27,7 @@ namespace teachos::arch::memory::allocator area_frame_allocator(multiboot::memory_information mem_info); /** - * @brief Allocate memory by finding and returning a free physical_frame. + * @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 @@ -35,17 +35,19 @@ namespace teachos::arch::memory::allocator * - 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; /** - * @brief Deallocates a previously allocated physical_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 ben alocated in the first place. * - * @param physical_frame Previously allocated physical_frame that should be allocated. + * @param physical_frame Previously allocated physical_frame that should be deallocated. */ auto deallocate_frame(physical_frame physical_frame) -> void; diff --git a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp new file mode 100644 index 0000000..70c7de6 --- /dev/null +++ b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp @@ -0,0 +1,44 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP + +#include "arch/memory/allocator/physical_frame.hpp" + +#include +#include + +namespace teachos::arch::memory::allocator +{ + /** + * @brief Allocates memory using memory areas read from the multiboot2 information pointer. + */ + struct tiny_frame_allocator + { + /** + * @brief Defaulted constructor. + */ + tiny_frame_allocator() = default; + + /** + * @brief Allocate memory by finding and returning one of the three free physical frames. + * + * @return First free physical frames of the three frames held by this allocator or nullopt if we used up all three + * frames already. + */ + auto allocate_frame() -> std::optional; + + /** + * @brief Deallocates one of the three previously allocated physical frames. + * + * @note If more than the three frames are deallocated the method will halt execution, because it can only hold 3 + * frames. + * + * @param physical_frame Previously allocated physical_frame that should be deallocated. + */ + auto deallocate_frame(physical_frame physical_frame) -> void; + + private: + std::array, 3U> frames = {}; + }; +} // namespace teachos::arch::memory::allocator + +#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP -- cgit v1.2.3 From 98edc76893b2e22ccdbd81a4a3f1e1113c712cba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 1 Nov 2024 07:44:28 +0000 Subject: Extract contract into seperate file and create tinyallocator constructor --- .../arch/memory/allocator/area_frame_allocator.hpp | 6 ------ arch/x86_64/include/arch/memory/allocator/concept.hpp | 17 +++++++++++++++++ .../arch/memory/allocator/tiny_frame_allocator.hpp | 9 +++++++-- arch/x86_64/include/arch/memory/paging/page_mapper.hpp | 2 +- arch/x86_64/include/arch/memory/paging/page_table.hpp | 2 +- 5 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 arch/x86_64/include/arch/memory/allocator/concept.hpp (limited to 'arch/x86_64/include') 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 6135184..4b6c2d4 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 @@ -8,12 +8,6 @@ namespace teachos::arch::memory::allocator { - template - concept FrameAllocator = requires(T t, physical_frame a) { - { t.allocate_frame() } -> std::same_as>; - { t.deallocate_frame(a) } -> std::same_as; - }; - /** * @brief Allocates memory using memory areas read from the multiboot2 information pointer. */ diff --git a/arch/x86_64/include/arch/memory/allocator/concept.hpp b/arch/x86_64/include/arch/memory/allocator/concept.hpp new file mode 100644 index 0000000..0aa45c6 --- /dev/null +++ b/arch/x86_64/include/arch/memory/allocator/concept.hpp @@ -0,0 +1,17 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_CONCEPT_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_CONCEPT_HPP + +#include "arch/memory/allocator/physical_frame.hpp" + +#include + +namespace teachos::arch::memory::allocator +{ + template + concept FrameAllocator = requires(T t, physical_frame a) { + { t.allocate_frame() } -> std::same_as>; + { t.deallocate_frame(a) } -> std::same_as; + }; +} // namespace teachos::arch::memory::allocator + +#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_CONCEPT_HPP diff --git a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp index 70c7de6..a028e30 100644 --- a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp @@ -1,10 +1,10 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP #define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP +#include "arch/memory/allocator/concept.hpp" #include "arch/memory/allocator/physical_frame.hpp" #include -#include namespace teachos::arch::memory::allocator { @@ -16,7 +16,12 @@ namespace teachos::arch::memory::allocator /** * @brief Defaulted constructor. */ - tiny_frame_allocator() = default; + template + tiny_frame_allocator(T & allocator) + : frames{allocator.allocate_frame(), allocator.allocate_frame(), allocator.allocate_frame()} + { + // Nothing to do + } /** * @brief Allocate memory by finding and returning one of the three free physical frames. diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index a9f8eb8..26b8171 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -2,7 +2,7 @@ #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP #include "arch/exception_handling/assert.hpp" -#include "arch/memory/allocator/area_frame_allocator.hpp" +#include "arch/memory/allocator/concept.hpp" #include "arch/memory/paging/virtual_page.hpp" #include diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 31fb58c..b9ea44b 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -2,7 +2,7 @@ #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP #include "arch/exception_handling/assert.hpp" -#include "arch/memory/allocator/area_frame_allocator.hpp" +#include "arch/memory/allocator/concept.hpp" #include "arch/memory/paging/page_entry.hpp" namespace teachos::arch::memory::paging -- cgit v1.2.3 From b0f666ba15ff2db3178ca54242308e3dd5dd6faa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 1 Nov 2024 09:34:19 +0000 Subject: Fix comment --- arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp index a028e30..9417c37 100644 --- a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp @@ -14,7 +14,12 @@ namespace teachos::arch::memory::allocator struct tiny_frame_allocator { /** - * @brief Defaulted constructor. + * @brief Constructor. + * + * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and + * deallocate method. + * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate + * entries *when a new page table is required. */ template tiny_frame_allocator(T & allocator) -- cgit v1.2.3 From 29c51a2cc30060bd904b06cbe6913755352c48c7 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Fri, 1 Nov 2024 10:08:50 +0000 Subject: create temporary page implementation --- .../arch/memory/allocator/tiny_frame_allocator.hpp | 14 ++++- .../include/arch/memory/paging/page_table.hpp | 18 +++--- .../include/arch/memory/paging/temporary_page.hpp | 68 ++++++++++++++++++++++ 3 files changed, 88 insertions(+), 12 deletions(-) create mode 100644 arch/x86_64/include/arch/memory/paging/temporary_page.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp index a028e30..77d1b43 100644 --- a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp @@ -1,6 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP #define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP +#include "arch/memory/allocator/area_frame_allocator.hpp" #include "arch/memory/allocator/concept.hpp" #include "arch/memory/allocator/physical_frame.hpp" @@ -16,10 +17,17 @@ namespace teachos::arch::memory::allocator /** * @brief Defaulted constructor. */ - template - tiny_frame_allocator(T & allocator) - : frames{allocator.allocate_frame(), allocator.allocate_frame(), allocator.allocate_frame()} + tiny_frame_allocator(area_frame_allocator & allocator) + : frames{} { + for (auto & frame : frames) + { + auto temp_frame = allocator.allocate_frame(); + if (temp_frame.has_value()) + { + frame.emplace(temp_frame.value()); + } + } // Nothing to do } diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index b9ea44b..9449ef2 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -41,10 +41,10 @@ namespace teachos::arch::memory::paging /** * @brief Constructor. * - * @param handle Underlying page table the handle should point to. - * @param handle_level Level the underlying page table is on, used to ensure safety. + * @param table Underlying page table the handle should point to. + * @param table_level Level the underlying page table is on, used to ensure safety. */ - page_table_handle(page_table * handle, level handle_level); + page_table_handle(page_table * table, level table_level); /** * @brief Set every entry of the page to unused. @@ -57,9 +57,9 @@ namespace teachos::arch::memory::paging auto is_empty() const -> bool; /** - * @brief Get the current handle level. + * @brief Get the current table level. * - * @return Current handle level. + * @return Current table level. */ auto get_level() const -> level; @@ -120,7 +120,7 @@ namespace teachos::arch::memory::paging auto operator[](std::size_t index) const -> entry const &; /** - * @brief Decrements the page table handle level enum by one, is defined so we can use it as a replacement for an + * @brief Decrements the page table level enum by one, is defined so we can use it as a replacement for an * int index in a range based for loop. * * @note Will halt execution if called with page_table_handle::LEVEL1, because there is no level below. Has to be @@ -137,9 +137,9 @@ namespace teachos::arch::memory::paging friend auto operator--(level & value) -> level &; private: - page_table * handle; ///< Handle to underlying page table, can never be null (invariant ensured by constructor) - level handle_level; ///< Level page table is currently on, depends on how often next_level was - ///< called successfully. + page_table * table; ///< Handle to underlying page table, can never be null (invariant ensured by constructor) + level table_level; ///< Level page table is currently on, depends on how often next_level was + ///< called successfully. }; } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp new file mode 100644 index 0000000..ae806c8 --- /dev/null +++ b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp @@ -0,0 +1,68 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_TEMPORARY_PAGE_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_TEMPORARY_PAGE_HPP + +#include "arch/memory/allocator/physical_frame.hpp" +#include "arch/memory/allocator/tiny_frame_allocator.hpp" +#include "arch/memory/paging/page_table.hpp" +#include "arch/memory/paging/virtual_page.hpp" + +namespace teachos::arch::memory::paging +{ + + /** + * @brief + * + */ + struct temporary_page + { + /** + * @brief Construct a new temporary page object + * + * @tparam T + * @param page + * @param allocator + */ + template + temporary_page(virtual_page page, T & allocator) + : page{page} + , allocator{allocator} + { + // Nothing to do + } + + /** + * @brief + * + * @param frame + */ + auto zero_entries() -> void; + + private: + /** + * @brief + * + * @param frame + * @return virtual_address + */ + auto map_to_frame(allocator::physical_frame frame) -> virtual_address; + + /** + * @brief + * + */ + auto unmap() -> void; + + /** + * @brief + * + * @param frame + * @return page_table_handle + */ + auto map_table_frame(allocator::physical_frame frame) -> page_table_handle; + + virtual_page page; + allocator::tiny_frame_allocator allocator; + }; +} // namespace teachos::arch::memory::paging + +#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_TEMPORARY_PAGE_HPP \ No newline at end of file -- cgit v1.2.3 From defb727b2d0ac902e10e9736440779495b8b51a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 1 Nov 2024 12:56:22 +0000 Subject: Move methods into seperate class. --- .../include/arch/memory/paging/page_mapper.hpp | 314 +++++++++++---------- 1 file changed, 170 insertions(+), 144 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp index 26b8171..20d9afc 100644 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp @@ -11,8 +11,173 @@ namespace teachos::arch::memory::paging { - namespace + /** + * @brief Currently active level 4 page table, is used to ensure there is only ever one valid instance and it cannot + * be copied or constructed again. + */ + struct active_page_table { + /** + * @brief Creates a single instance of an active level 4 page table table and returns the created instance or + * alternatively returns the previously created instance instead. The instance is owned by this method and is + * static, meaning it lives on for the complete lifetime of the program. + * + * @return Active single unique instance of the level 4 page table. + */ + static auto create_or_get() -> active_page_table &; + + /** + * @brief Translates virtual address into corresponding physical address. Calls translate_page under the hood. + * + * @param address Virtual address we want to translate into physical one. + * @return Physical address corresponding to the provided virtual address. + */ + auto translate_address(virtual_address address) -> std::optional; + + /** + * @brief Translates page into physical frame, will first attempt to parse normally using default page size and if + * it failed attempt to parse using huge pages. + * + * @param page Page to translate into physical frame. + * @return Physical frame corresponding to the provided virtual page. + */ + auto translate_page(virtual_page page) -> std::optional; + + /** + * @brief Translates huge page into actual physical frame. + * + * @param page Page to translate into physical frame. + * @return Physical frame corresponding to the provided virtual page. + */ + auto translate_huge_page(virtual_page page) -> std::optional; + + /** + * @brief Maps a virtual page to a physical frame in the page table with the specified flags. + * + * @note Allocates and maps an entry in every page level if it does not exists yet down to level 1. If the level 1 + * page table already exists it halts execution instead. + * + * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and + * deallocate method. + * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate + * entries when a new page table is required. + * @param page Virtual page that is being mapped. + * @param frame Physical frame that the virtual page will be mapped to. + * @param flags A bitset of flags that configure the page table entry for this mapping. + */ + template + auto map_page_to_frame(T & allocator, virtual_page page, allocator::physical_frame frame, + std::bitset<64U> flags) -> void + { + auto current_handle = active_handle; + + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) + { + current_handle = current_handle.next_table_or_create(allocator, page.get_level_index(level)); + } + + auto & level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; + arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE), + "[Page Mapper] Unable to map huge pages"); + arch::exception_handling::assert(level1_entry.is_unused(), "[Page Mapper] Page table entry is already used"); + level1_entry.set_entry(frame, flags.to_ulong() | entry::PRESENT); + } + + /** + * @brief Allocates the next free frame and then uses that frame to call map_page_to_frame. + * + * @see map_page_to_frame + */ + template + auto map_next_free_page_to_frame(T & allocator, virtual_page page, std::bitset<64U> flags) -> void + { + auto const frame = allocator.allocate_frame(); + exception_handling::assert(frame.has_value(), "[Page mapper] Out of memory exception"); + map_page_to_frame(allocator, page, frame.value(), flags); + } + + /** + * @brief Gets the corresponding page the given frame has to be contained in and uses that to call + * map_page_to_frame. + * + * @see map_page_to_frame + */ + template + auto identity_map(T & allocator, allocator::physical_frame frame, std::bitset<64U> flags) -> void + { + auto const page = virtual_page::containing_address(frame.start_address()); + map_page_to_frame(allocator, page, frame, flags); + } + + /** + * @brief Unmaps the virtual page from the previously mapped to physical frame and resets the flags. + * + * @note Deallocates and unmaps the entry in every page level if this page was the last one up to level 4 and + * ensures to clear the Translation Lookaside Buffer, so that the unmapped value is removed from cache as well. + * + * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and + * deallocate method. + * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate + * entries when a new page table is required. + * @param page Virtual page that is being unmapped. + */ + template + auto unmap_page(T & allocator, virtual_page page) -> void + { + exception_handling::assert(translate_page(page).has_value(), + "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); + + auto current_handle = active_handle; + std::array handles{current_handle, current_handle, current_handle, current_handle}; + + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) + { + auto const level_index = page.get_level_index(level); + auto const next_handle = current_handle.next_table(level_index); + // The next table method failed even tough the page has to be mapped already, because translate_page did not + // fail. This can only mean that we attempted to unmap a huge page, which is not supported in the first place. + exception_handling::assert(next_handle.has_value(), "[Page Mapper] Unable to unmap huge pages"); + current_handle = next_handle.value(); + // The level is used as the index, because it ensures the first level is the lowest one and then the remaining + // levels in ascending order. This is required, because we first have to clear the Level 1 page entry to check + // if the Level 1 page is now empty, to clear the Level 2 page entry, which will then also check if the Level 2 + // page is empty and clear the Level 3 page entry and so on. + handles.at(level - 1U) = current_handle; + } + + // Unmaps all entries starting from the Level 1 page table, and unmaps higher levels as well if that entry was the + // last one. We check if it was the last one using is empty on the page table handle, when we have removed the + // page to be unmapped. + for (auto & handle : handles) + { + unmap_page_table_entry(allocator, page, handle); + if (!handle.is_empty()) + { + break; + } + } + invalidate_page_cache(page.start_address()); + } + + private: + /** + * @brief Private constructor should only be used by create or get method, which ensures to create only ever one + * instance. + * + * @param active_handle Handle to the underlying currently active level 4 page table. + */ + active_page_table(page_table_handle active_handle); + + /** + * @brief Deleted copy constructor. + */ + active_page_table(active_page_table const &) = delete; + + /** + * @brief Deleted copy assignment operator. + */ + active_page_table & operator=(active_page_table const &) = delete; + /** * @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained * in. See https://www.felixcloutier.com/x86/invlpg for more information on the used x86 instruction. @@ -20,7 +185,7 @@ namespace teachos::arch::memory::paging * @param address Memory address, which will be used to determine the contained page and flush the TLB entry for * that page. */ - auto invalidate_page_cache(virtual_address address) -> void + static auto invalidate_page_cache(virtual_address address) -> void { asm volatile("invlpg (%0)" ::"r"(address) : "memory"); } @@ -36,7 +201,7 @@ namespace teachos::arch::memory::paging * @param handle Page Table handle we want to access the entry that should be cleared on. */ template - auto unmap_page_table_entry(T & allocator, virtual_page page, page_table_handle & handle) -> void + static auto unmap_page_table_entry(T & allocator, virtual_page page, page_table_handle & handle) -> void { auto level_index = page.get_level_index(handle.get_level()); auto & entry = handle[level_index]; @@ -46,148 +211,9 @@ namespace teachos::arch::memory::paging entry.set_unused(); allocator.deallocate_frame(frame.value()); } - } // namespace - - /** - * @brief Creates a single instance of the level 4 page table table and returns handle to it or alternatively returns - * the previously created handle instead. The instance is owned by this method and is static, meaning it lives on for - * the complete lifetime of the program. - * - * @return Handle to the single unique instance of the level 4 page table. - */ - auto create_or_get() -> page_table_handle; - - /** - * @brief Translates virtual address into corresponding physical address. Calls translate_page under the hood. - * - * @param address Virtual address we want to translate into physical one. - * @return Physical address corresponding to the provided virtual address. - */ - auto translate_address(virtual_address address) -> std::optional; - - /** - * @brief Translates page into physical frame, will first attempt to parse normally using default page size and if - * it failed attempt to parse using huge pages. - * - * @param page Page to translate into physical frame. - * @return Physical frame corresponding to the provided virtual page. - */ - auto translate_page(virtual_page page) -> std::optional; - - /** - * @brief Translates huge page into actual physical frame. - * - * @param page Page to translate into physical frame. - * @return Physical frame corresponding to the provided virtual page. - */ - auto translate_huge_page(virtual_page page) -> std::optional; - - /** - * @brief Maps a virtual page to a physical frame in the page table with the specified flags. - * - * @note Allocates and maps an entry in every page level if it does not exists yet down to level 1. If the level 1 - * page table already exists it halts execution instead. - * - * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and - * deallocate method. - * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate entries - * when a new page table is required. - * @param page Virtual page that is being mapped. - * @param frame Physical frame that the virtual page will be mapped to. - * @param flags A bitset of flags that configure the page table entry for this mapping. - */ - template - auto map_page_to_frame(T & allocator, virtual_page page, allocator::physical_frame frame, - std::bitset<64U> flags) -> void - { - auto current_handle = create_or_get(); - - for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) - { - current_handle = current_handle.next_table_or_create(allocator, page.get_level_index(level)); - } - auto & level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; - arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE), - "[Page Mapper] Unable to map huge pages"); - arch::exception_handling::assert(level1_entry.is_unused(), "[Page Mapper] Page table entry is already used"); - level1_entry.set_entry(frame, flags.to_ulong() | entry::PRESENT); - } - - /** - * @brief Allocates the next free frame and then uses that frame to call map_page_to_frame. - * - * @see map_page_to_frame - */ - template - auto map_next_free_page_to_frame(T & allocator, virtual_page page, std::bitset<64U> flags) -> void - { - auto const frame = allocator.allocate_frame(); - exception_handling::assert(frame.has_value(), "[Page mapper] Out of memory exception"); - map_page_to_frame(allocator, page, frame.value(), flags); - } - - /** - * @brief Gets the corresponding page the given frame has to be contained in and uses that to call map_page_to_frame. - * - * @see map_page_to_frame - */ - template - auto identity_map(T & allocator, allocator::physical_frame frame, std::bitset<64U> flags) -> void - { - auto const page = virtual_page::containing_address(frame.start_address()); - map_page_to_frame(allocator, page, frame, flags); - } - - /** - * @brief Unmaps the virtual page from the previously mapped to physical frame and resets the flags. - * - * @note Deallocates and unmaps the entry in every page level if this page was the last one up to level 4 and ensures - * to clear the Translation Lookaside Buffer, so that the unmapped value is removed from cache as well. - * - * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and - * deallocate method. - * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate entries - * when a new page table is required. - * @param page Virtual page that is being unmapped. - */ - template - auto unmap_page(T & allocator, virtual_page page) -> void - { - exception_handling::assert(translate_page(page).has_value(), - "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); - - auto current_handle = create_or_get(); - std::array handles{current_handle, current_handle, current_handle, current_handle}; - - for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) - { - auto const level_index = page.get_level_index(level); - auto const next_handle = current_handle.next_table(level_index); - // The next table method failed even tough the page has to be mapped already, because translate_page did not fail. - // This can only mean that we attempted to unmap a huge page, which is not supported in the first place. - exception_handling::assert(next_handle.has_value(), "[Page Mapper] Unable to unmap huge pages"); - current_handle = next_handle.value(); - // The level is used as the index, because it ensures the first level is the lowest one and then the remaining - // levels in ascending order. This is required, because we first have to clear the Level 1 page entry to check if - // the Level 1 page is now empty, to clear the Level 2 page entry, which will then also check if the Level 2 page - // is empty and clear the Level 3 page entry and so on. - handles.at(level - 1U) = current_handle; - } - - // Unmaps all entries starting from the Level 1 page table, and unmaps higher levels as well if that entry was the - // last one. We check if it was the last one using is empty on the page table handle, when we have removed the page - // to be unmapped. - for (auto & handle : handles) - { - unmap_page_table_entry(allocator, page, handle); - if (!handle.is_empty()) - { - break; - } - } - invalidate_page_cache(page.start_address()); - } + page_table_handle active_handle; + }; } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP -- cgit v1.2.3 From b0d917bc8ad95e282f25949c489dfc1c06b91b83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 1 Nov 2024 13:02:14 +0000 Subject: Adjust temporary page to changes --- arch/x86_64/include/arch/memory/paging/temporary_page.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp index ae806c8..0293dd9 100644 --- a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp @@ -3,12 +3,12 @@ #include "arch/memory/allocator/physical_frame.hpp" #include "arch/memory/allocator/tiny_frame_allocator.hpp" +#include "arch/memory/paging/page_mapper.hpp" #include "arch/memory/paging/page_table.hpp" #include "arch/memory/paging/virtual_page.hpp" namespace teachos::arch::memory::paging { - /** * @brief * @@ -35,7 +35,7 @@ namespace teachos::arch::memory::paging * * @param frame */ - auto zero_entries() -> void; + auto zero_entries(active_page_table & active_table) -> void; private: /** @@ -44,13 +44,13 @@ namespace teachos::arch::memory::paging * @param frame * @return virtual_address */ - auto map_to_frame(allocator::physical_frame frame) -> virtual_address; + auto map_to_frame(allocator::physical_frame frame, active_page_table & active_table) -> virtual_address; /** * @brief * */ - auto unmap() -> void; + auto unmap(active_page_table & active_table) -> void; /** * @brief @@ -58,7 +58,7 @@ namespace teachos::arch::memory::paging * @param frame * @return page_table_handle */ - auto map_table_frame(allocator::physical_frame frame) -> page_table_handle; + auto map_table_frame(allocator::physical_frame frame, active_page_table & active_table) -> page_table_handle; virtual_page page; allocator::tiny_frame_allocator allocator; -- cgit v1.2.3 From b38ce5e24222ec97b45e1f87da4a392859947064 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Fri, 1 Nov 2024 13:16:13 +0000 Subject: add doxygen comments --- .../include/arch/memory/allocator/concept.hpp | 5 ++++ .../include/arch/memory/paging/temporary_page.hpp | 30 ++++++++++++---------- 2 files changed, 21 insertions(+), 14 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/concept.hpp b/arch/x86_64/include/arch/memory/allocator/concept.hpp index 0aa45c6..4a7ab72 100644 --- a/arch/x86_64/include/arch/memory/allocator/concept.hpp +++ b/arch/x86_64/include/arch/memory/allocator/concept.hpp @@ -7,6 +7,11 @@ namespace teachos::arch::memory::allocator { + /** + * @brief Frame allocator concept + * + * @tparam T + */ template concept FrameAllocator = requires(T t, physical_frame a) { { t.allocate_frame() } -> std::same_as>; diff --git a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp index 0293dd9..c42745a 100644 --- a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp @@ -10,17 +10,16 @@ namespace teachos::arch::memory::paging { /** - * @brief - * + * @brief A temporary page used to remap the kernel. */ struct temporary_page { /** * @brief Construct a new temporary page object * - * @tparam T - * @param page - * @param allocator + * @tparam FrameAllocator concept + * @param page Page to turn into temporary page + * @param allocator Frame allocator used to fill page */ template temporary_page(virtual_page page, T & allocator) @@ -31,32 +30,35 @@ namespace teachos::arch::memory::paging } /** - * @brief + * @brief Set all page table entries to unused. * - * @param frame + * @param active_table the page table whose values are set to unused. */ auto zero_entries(active_page_table & active_table) -> void; private: /** - * @brief + * @brief Map the temporary page to a frame. * - * @param frame - * @return virtual_address + * @param frame The frame to which the page is mapped. + * @param active_table The current active page table. + * @return The virtual address of the page. */ auto map_to_frame(allocator::physical_frame frame, active_page_table & active_table) -> virtual_address; /** - * @brief + * @brief Unmap the current page. * + * @param active_table The current active page table. */ auto unmap(active_page_table & active_table) -> void; /** - * @brief + * @brief Map the temporary page to a frame. * - * @param frame - * @return page_table_handle + * @param frame The frame to which the page is mapped. + * @param active_table The current active page table. + * @return level1 page table handle containing the mapped page. */ auto map_table_frame(allocator::physical_frame frame, active_page_table & active_table) -> page_table_handle; -- cgit v1.2.3 From 31e1ac359eb4b84bdd81f768b2de327193976a55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 1 Nov 2024 13:22:02 +0000 Subject: Remove static page mapper and replace with unique active and inactive page table classes. --- .../arch/memory/allocator/tiny_frame_allocator.hpp | 10 +- .../arch/memory/paging/active_page_table.hpp | 218 ++++++++++++++++++++ .../arch/memory/paging/inactive_page_table.hpp | 15 ++ .../include/arch/memory/paging/page_mapper.hpp | 219 --------------------- .../include/arch/memory/paging/temporary_page.hpp | 2 +- 5 files changed, 235 insertions(+), 229 deletions(-) create mode 100644 arch/x86_64/include/arch/memory/paging/active_page_table.hpp create mode 100644 arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp delete mode 100644 arch/x86_64/include/arch/memory/paging/page_mapper.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp index 4bcec1c..e55b376 100644 --- a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp @@ -23,16 +23,8 @@ namespace teachos::arch::memory::allocator * entries *when a new page table is required. */ tiny_frame_allocator(area_frame_allocator & allocator) - : frames{} + : frames{allocator.allocate_frame(), allocator.allocate_frame(), allocator.allocate_frame()} { - for (auto & frame : frames) - { - auto temp_frame = allocator.allocate_frame(); - if (temp_frame.has_value()) - { - frame.emplace(temp_frame.value()); - } - } // Nothing to do } diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp new file mode 100644 index 0000000..8011ee0 --- /dev/null +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -0,0 +1,218 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_ACTIVE_PAGE_TABLE_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_ACTIVE_PAGE_TABLE_HPP + +#include "arch/exception_handling/assert.hpp" +#include "arch/memory/allocator/concept.hpp" +#include "arch/memory/paging/virtual_page.hpp" + +#include +#include + +namespace teachos::arch::memory::paging +{ + /** + * @brief Currently active level 4 page table, is used to ensure there is only ever one valid instance and it cannot + * be copied or constructed again. + */ + struct active_page_table + { + /** + * @brief Creates a single instance of an active level 4 page table table and returns the created instance or + * alternatively returns the previously created instance instead. The instance is owned by this method and is + * static, meaning it lives on for the complete lifetime of the program. + * + * @return Active single unique instance of the level 4 page table. + */ + static auto create_or_get() -> active_page_table &; + + /** + * @brief Translates virtual address into corresponding physical address. Calls translate_page under the hood. + * + * @param address Virtual address we want to translate into physical one. + * @return Physical address corresponding to the provided virtual address. + */ + auto translate_address(virtual_address address) -> std::optional; + + /** + * @brief Translates page into physical frame, will first attempt to parse normally using default page size and if + * it failed attempt to parse using huge pages. + * + * @param page Page to translate into physical frame. + * @return Physical frame corresponding to the provided virtual page. + */ + auto translate_page(virtual_page page) -> std::optional; + + /** + * @brief Translates huge page into actual physical frame. + * + * @param page Page to translate into physical frame. + * @return Physical frame corresponding to the provided virtual page. + */ + auto translate_huge_page(virtual_page page) -> std::optional; + + /** + * @brief Maps a virtual page to a physical frame in the page table with the specified flags. + * + * @note Allocates and maps an entry in every page level if it does not exists yet down to level 1. If the level 1 + * page table already exists it halts execution instead. + * + * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and + * deallocate method. + * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate + * entries when a new page table is required. + * @param page Virtual page that is being mapped. + * @param frame Physical frame that the virtual page will be mapped to. + * @param flags A bitset of flags that configure the page table entry for this mapping. + */ + template + auto map_page_to_frame(T & allocator, virtual_page page, allocator::physical_frame frame, + std::bitset<64U> flags) -> void + { + auto current_handle = active_handle; + + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) + { + current_handle = current_handle.next_table_or_create(allocator, page.get_level_index(level)); + } + + auto & level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; + arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE), + "[Page Mapper] Unable to map huge pages"); + arch::exception_handling::assert(level1_entry.is_unused(), "[Page Mapper] Page table entry is already used"); + level1_entry.set_entry(frame, flags.to_ulong() | entry::PRESENT); + } + + /** + * @brief Allocates the next free frame and then uses that frame to call map_page_to_frame. + * + * @see map_page_to_frame + */ + template + auto map_next_free_page_to_frame(T & allocator, virtual_page page, std::bitset<64U> flags) -> void + { + auto const frame = allocator.allocate_frame(); + exception_handling::assert(frame.has_value(), "[Page mapper] Out of memory exception"); + map_page_to_frame(allocator, page, frame.value(), flags); + } + + /** + * @brief Gets the corresponding page the given frame has to be contained in and uses that to call + * map_page_to_frame. + * + * @see map_page_to_frame + */ + template + auto identity_map(T & allocator, allocator::physical_frame frame, std::bitset<64U> flags) -> void + { + auto const page = virtual_page::containing_address(frame.start_address()); + map_page_to_frame(allocator, page, frame, flags); + } + + /** + * @brief Unmaps the virtual page from the previously mapped to physical frame and resets the flags. + * + * @note Deallocates and unmaps the entry in every page level if this page was the last one up to level 4 and + * ensures to clear the Translation Lookaside Buffer, so that the unmapped value is removed from cache as well. + * + * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and + * deallocate method. + * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate + * entries when a new page table is required. + * @param page Virtual page that is being unmapped. + */ + template + auto unmap_page(T & allocator, virtual_page page) -> void + { + exception_handling::assert(translate_page(page).has_value(), + "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); + + auto current_handle = active_handle; + std::array handles{current_handle, current_handle, current_handle, current_handle}; + + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) + { + auto const level_index = page.get_level_index(level); + auto const next_handle = current_handle.next_table(level_index); + // The next table method failed even tough the page has to be mapped already, because translate_page did not + // fail. This can only mean that we attempted to unmap a huge page, which is not supported in the first place. + exception_handling::assert(next_handle.has_value(), "[Page Mapper] Unable to unmap huge pages"); + current_handle = next_handle.value(); + // The level is used as the index, because it ensures the first level is the lowest one and then the remaining + // levels in ascending order. This is required, because we first have to clear the Level 1 page entry to check + // if the Level 1 page is now empty, to clear the Level 2 page entry, which will then also check if the Level 2 + // page is empty and clear the Level 3 page entry and so on. + handles.at(level - 1U) = current_handle; + } + + // Unmaps all entries starting from the Level 1 page table, and unmaps higher levels as well if that entry was the + // last one. We check if it was the last one using is empty on the page table handle, when we have removed the + // page to be unmapped. + for (auto & handle : handles) + { + unmap_page_table_entry(allocator, page, handle); + if (!handle.is_empty()) + { + break; + } + } + invalidate_page_cache(page.start_address()); + } + + private: + /** + * @brief Private constructor should only be used by create or get method, which ensures to create only ever one + * instance. + * + * @param active_handle Handle to the underlying currently active level 4 page table. + */ + active_page_table(page_table_handle active_handle); + + /** + * @brief Deleted copy constructor. + */ + active_page_table(active_page_table const &) = delete; + + /** + * @brief Deleted copy assignment operator. + */ + active_page_table & operator=(active_page_table const &) = delete; + + /** + * @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained + * in. See https://www.felixcloutier.com/x86/invlpg for more information on the used x86 instruction. + * + * @param address Memory address, which will be used to determine the contained page and flush the TLB entry for + * that page. + */ + static auto invalidate_page_cache(virtual_address address) -> void + { + asm volatile("invlpg (%0)" ::"r"(address) : "memory"); + } + + /** + * @brief Unmaps specific page at the current internal handle level. + * + * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and + * deallocate method. + * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate + * entries *when a new page table is required. + * @param page Virtual page that is being unmapped. + * @param handle Page Table handle we want to access the entry that should be cleared on. + */ + template + static auto unmap_page_table_entry(T & allocator, virtual_page page, page_table_handle & handle) -> void + { + auto level_index = page.get_level_index(handle.get_level()); + auto & entry = handle[level_index]; + auto const frame = entry.calculate_pointed_to_frame(); + exception_handling::assert(frame.has_value(), + "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); + entry.set_unused(); + allocator.deallocate_frame(frame.value()); + } + + page_table_handle active_handle; + }; +} // namespace teachos::arch::memory::paging + +#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_ACTIVE_PAGE_TABLE_HPP diff --git a/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp b/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp new file mode 100644 index 0000000..4285fc2 --- /dev/null +++ b/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp @@ -0,0 +1,15 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_INACTIVE_PAGE_TABLE_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_INACTIVE_PAGE_TABLE_HPP + +#include "arch/memory/allocator/physical_frame.hpp" + +namespace teachos::arch::memory::paging +{ + struct inactive_page_table + { + private: + allocator::physical_frame page_table_level_4_frame; + }; +} // namespace teachos::arch::memory::paging + +#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_INACTIVE_PAGE_TABLE_HPP diff --git a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp b/arch/x86_64/include/arch/memory/paging/page_mapper.hpp deleted file mode 100644 index 20d9afc..0000000 --- a/arch/x86_64/include/arch/memory/paging/page_mapper.hpp +++ /dev/null @@ -1,219 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP - -#include "arch/exception_handling/assert.hpp" -#include "arch/memory/allocator/concept.hpp" -#include "arch/memory/paging/virtual_page.hpp" - -#include -#include -#include - -namespace teachos::arch::memory::paging -{ - /** - * @brief Currently active level 4 page table, is used to ensure there is only ever one valid instance and it cannot - * be copied or constructed again. - */ - struct active_page_table - { - /** - * @brief Creates a single instance of an active level 4 page table table and returns the created instance or - * alternatively returns the previously created instance instead. The instance is owned by this method and is - * static, meaning it lives on for the complete lifetime of the program. - * - * @return Active single unique instance of the level 4 page table. - */ - static auto create_or_get() -> active_page_table &; - - /** - * @brief Translates virtual address into corresponding physical address. Calls translate_page under the hood. - * - * @param address Virtual address we want to translate into physical one. - * @return Physical address corresponding to the provided virtual address. - */ - auto translate_address(virtual_address address) -> std::optional; - - /** - * @brief Translates page into physical frame, will first attempt to parse normally using default page size and if - * it failed attempt to parse using huge pages. - * - * @param page Page to translate into physical frame. - * @return Physical frame corresponding to the provided virtual page. - */ - auto translate_page(virtual_page page) -> std::optional; - - /** - * @brief Translates huge page into actual physical frame. - * - * @param page Page to translate into physical frame. - * @return Physical frame corresponding to the provided virtual page. - */ - auto translate_huge_page(virtual_page page) -> std::optional; - - /** - * @brief Maps a virtual page to a physical frame in the page table with the specified flags. - * - * @note Allocates and maps an entry in every page level if it does not exists yet down to level 1. If the level 1 - * page table already exists it halts execution instead. - * - * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and - * deallocate method. - * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate - * entries when a new page table is required. - * @param page Virtual page that is being mapped. - * @param frame Physical frame that the virtual page will be mapped to. - * @param flags A bitset of flags that configure the page table entry for this mapping. - */ - template - auto map_page_to_frame(T & allocator, virtual_page page, allocator::physical_frame frame, - std::bitset<64U> flags) -> void - { - auto current_handle = active_handle; - - for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) - { - current_handle = current_handle.next_table_or_create(allocator, page.get_level_index(level)); - } - - auto & level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; - arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE), - "[Page Mapper] Unable to map huge pages"); - arch::exception_handling::assert(level1_entry.is_unused(), "[Page Mapper] Page table entry is already used"); - level1_entry.set_entry(frame, flags.to_ulong() | entry::PRESENT); - } - - /** - * @brief Allocates the next free frame and then uses that frame to call map_page_to_frame. - * - * @see map_page_to_frame - */ - template - auto map_next_free_page_to_frame(T & allocator, virtual_page page, std::bitset<64U> flags) -> void - { - auto const frame = allocator.allocate_frame(); - exception_handling::assert(frame.has_value(), "[Page mapper] Out of memory exception"); - map_page_to_frame(allocator, page, frame.value(), flags); - } - - /** - * @brief Gets the corresponding page the given frame has to be contained in and uses that to call - * map_page_to_frame. - * - * @see map_page_to_frame - */ - template - auto identity_map(T & allocator, allocator::physical_frame frame, std::bitset<64U> flags) -> void - { - auto const page = virtual_page::containing_address(frame.start_address()); - map_page_to_frame(allocator, page, frame, flags); - } - - /** - * @brief Unmaps the virtual page from the previously mapped to physical frame and resets the flags. - * - * @note Deallocates and unmaps the entry in every page level if this page was the last one up to level 4 and - * ensures to clear the Translation Lookaside Buffer, so that the unmapped value is removed from cache as well. - * - * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and - * deallocate method. - * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate - * entries when a new page table is required. - * @param page Virtual page that is being unmapped. - */ - template - auto unmap_page(T & allocator, virtual_page page) -> void - { - exception_handling::assert(translate_page(page).has_value(), - "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); - - auto current_handle = active_handle; - std::array handles{current_handle, current_handle, current_handle, current_handle}; - - for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) - { - auto const level_index = page.get_level_index(level); - auto const next_handle = current_handle.next_table(level_index); - // The next table method failed even tough the page has to be mapped already, because translate_page did not - // fail. This can only mean that we attempted to unmap a huge page, which is not supported in the first place. - exception_handling::assert(next_handle.has_value(), "[Page Mapper] Unable to unmap huge pages"); - current_handle = next_handle.value(); - // The level is used as the index, because it ensures the first level is the lowest one and then the remaining - // levels in ascending order. This is required, because we first have to clear the Level 1 page entry to check - // if the Level 1 page is now empty, to clear the Level 2 page entry, which will then also check if the Level 2 - // page is empty and clear the Level 3 page entry and so on. - handles.at(level - 1U) = current_handle; - } - - // Unmaps all entries starting from the Level 1 page table, and unmaps higher levels as well if that entry was the - // last one. We check if it was the last one using is empty on the page table handle, when we have removed the - // page to be unmapped. - for (auto & handle : handles) - { - unmap_page_table_entry(allocator, page, handle); - if (!handle.is_empty()) - { - break; - } - } - invalidate_page_cache(page.start_address()); - } - - private: - /** - * @brief Private constructor should only be used by create or get method, which ensures to create only ever one - * instance. - * - * @param active_handle Handle to the underlying currently active level 4 page table. - */ - active_page_table(page_table_handle active_handle); - - /** - * @brief Deleted copy constructor. - */ - active_page_table(active_page_table const &) = delete; - - /** - * @brief Deleted copy assignment operator. - */ - active_page_table & operator=(active_page_table const &) = delete; - - /** - * @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained - * in. See https://www.felixcloutier.com/x86/invlpg for more information on the used x86 instruction. - * - * @param address Memory address, which will be used to determine the contained page and flush the TLB entry for - * that page. - */ - static auto invalidate_page_cache(virtual_address address) -> void - { - asm volatile("invlpg (%0)" ::"r"(address) : "memory"); - } - - /** - * @brief Unmaps specific page at the current internal handle level. - * - * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and - * deallocate method. - * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate - * entries *when a new page table is required. - * @param page Virtual page that is being unmapped. - * @param handle Page Table handle we want to access the entry that should be cleared on. - */ - template - static auto unmap_page_table_entry(T & allocator, virtual_page page, page_table_handle & handle) -> void - { - auto level_index = page.get_level_index(handle.get_level()); - auto & entry = handle[level_index]; - auto const frame = entry.calculate_pointed_to_frame(); - exception_handling::assert(frame.has_value(), - "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); - entry.set_unused(); - allocator.deallocate_frame(frame.value()); - } - - page_table_handle active_handle; - }; -} // namespace teachos::arch::memory::paging - -#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_MAPPER_HPP diff --git a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp index c42745a..b658f7a 100644 --- a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp @@ -3,7 +3,7 @@ #include "arch/memory/allocator/physical_frame.hpp" #include "arch/memory/allocator/tiny_frame_allocator.hpp" -#include "arch/memory/paging/page_mapper.hpp" +#include "arch/memory/paging/active_page_table.hpp" #include "arch/memory/paging/page_table.hpp" #include "arch/memory/paging/virtual_page.hpp" -- cgit v1.2.3 From b9fdcc729c1875858297c0f3fb9d8e6feff71374 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Fri, 1 Nov 2024 14:29:58 +0000 Subject: implement temporary_page and update active/inactive page tables --- .../include/arch/memory/paging/active_page_table.hpp | 8 ++++++++ .../include/arch/memory/paging/inactive_page_table.hpp | 6 +++++- .../include/arch/memory/paging/temporary_page.hpp | 18 +++++++++--------- 3 files changed, 22 insertions(+), 10 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index 8011ee0..3fb2e65 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -3,6 +3,8 @@ #include "arch/exception_handling/assert.hpp" #include "arch/memory/allocator/concept.hpp" +#include "arch/memory/paging/inactive_page_table.hpp" +#include "arch/memory/paging/temporary_page.hpp" #include "arch/memory/paging/virtual_page.hpp" #include @@ -10,12 +12,15 @@ namespace teachos::arch::memory::paging { + /** * @brief Currently active level 4 page table, is used to ensure there is only ever one valid instance and it cannot * be copied or constructed again. */ struct active_page_table { + typedef void (*function)(active_page_table * active_page_table); + /** * @brief Creates a single instance of an active level 4 page table table and returns the created instance or * alternatively returns the previously created instance instead. The instance is owned by this method and is @@ -158,6 +163,8 @@ namespace teachos::arch::memory::paging invalidate_page_cache(page.start_address()); } + auto with(inactive_page_table inactive_page_table, temporary_page temporary_page, function f) -> void; + private: /** * @brief Private constructor should only be used by create or get method, which ensures to create only ever one @@ -213,6 +220,7 @@ namespace teachos::arch::memory::paging page_table_handle active_handle; }; + } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_ACTIVE_PAGE_TABLE_HPP diff --git a/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp b/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp index 4285fc2..62c196f 100644 --- a/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp @@ -2,12 +2,16 @@ #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_INACTIVE_PAGE_TABLE_HPP #include "arch/memory/allocator/physical_frame.hpp" +#include "arch/memory/paging/active_page_table.hpp" +#include "arch/memory/paging/temporary_page.hpp" namespace teachos::arch::memory::paging { struct inactive_page_table { - private: + inactive_page_table(allocator::physical_frame frame, active_page_table active_page_table, + temporary_page temporary_page); + allocator::physical_frame page_table_level_4_frame; }; } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp index b658f7a..a7552dd 100644 --- a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp @@ -36,31 +36,31 @@ namespace teachos::arch::memory::paging */ auto zero_entries(active_page_table & active_table) -> void; - private: /** - * @brief Map the temporary page to a frame. + * @brief Unmap the current page. * - * @param frame The frame to which the page is mapped. * @param active_table The current active page table. - * @return The virtual address of the page. */ - auto map_to_frame(allocator::physical_frame frame, active_page_table & active_table) -> virtual_address; + auto unmap(active_page_table & active_table) -> void; /** - * @brief Unmap the current page. + * @brief Map the temporary page to a frame. * + * @param frame The frame to which the page is mapped. * @param active_table The current active page table. + * @return level1 page table handle containing the mapped page. */ - auto unmap(active_page_table & active_table) -> void; + auto map_table_frame(allocator::physical_frame frame, active_page_table & active_table) -> page_table_handle; + private: /** * @brief Map the temporary page to a frame. * * @param frame The frame to which the page is mapped. * @param active_table The current active page table. - * @return level1 page table handle containing the mapped page. + * @return The virtual address of the page. */ - auto map_table_frame(allocator::physical_frame frame, active_page_table & active_table) -> page_table_handle; + auto map_to_frame(allocator::physical_frame frame, active_page_table & active_table) -> virtual_address; virtual_page page; allocator::tiny_frame_allocator allocator; -- cgit v1.2.3 From 08875c9c42c94dd23b16baa70b2be60cf35eb253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 1 Nov 2024 14:53:31 +0000 Subject: Fix circular dependency issue --- .../include/arch/memory/paging/active_page_table.hpp | 4 ---- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 14 ++++++++++++++ arch/x86_64/include/arch/memory/paging/temporary_page.hpp | 1 - 3 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index 3fb2e65..e876798 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -3,8 +3,6 @@ #include "arch/exception_handling/assert.hpp" #include "arch/memory/allocator/concept.hpp" -#include "arch/memory/paging/inactive_page_table.hpp" -#include "arch/memory/paging/temporary_page.hpp" #include "arch/memory/paging/virtual_page.hpp" #include @@ -163,8 +161,6 @@ namespace teachos::arch::memory::paging invalidate_page_cache(page.start_address()); } - auto with(inactive_page_table inactive_page_table, temporary_page temporary_page, function f) -> void; - private: /** * @brief Private constructor should only be used by create or get method, which ensures to create only ever one diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp new file mode 100644 index 0000000..085344a --- /dev/null +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -0,0 +1,14 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP + +#include "arch/memory/paging/active_page_table.hpp" +#include "arch/memory/paging/inactive_page_table.hpp" +#include "arch/memory/paging/temporary_page.hpp" + +namespace teachos::arch::memory::paging +{ + auto with(inactive_page_table inactive_page_table, temporary_page temporary_page, active_page_table::function f, + active_page_table & active_page_table) -> void; +} // namespace teachos::arch::memory::paging + +#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP diff --git a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp index a7552dd..0cadc29 100644 --- a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp @@ -4,7 +4,6 @@ #include "arch/memory/allocator/physical_frame.hpp" #include "arch/memory/allocator/tiny_frame_allocator.hpp" #include "arch/memory/paging/active_page_table.hpp" -#include "arch/memory/paging/page_table.hpp" #include "arch/memory/paging/virtual_page.hpp" namespace teachos::arch::memory::paging -- cgit v1.2.3 From 86f19267c7ca4e14ac6169f758130b3c27e62cdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 1 Nov 2024 15:10:30 +0000 Subject: Resolve compilation issues --- .../arch/memory/paging/active_page_table.hpp | 27 +++++++++++----------- .../include/arch/memory/paging/kernel_mapper.hpp | 12 ++++++++-- 2 files changed, 24 insertions(+), 15 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index e876798..e2c205b 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -10,6 +10,7 @@ namespace teachos::arch::memory::paging { + std::size_t constexpr PAGE_TABLE_LEVEL_4_ADDRESS = 0xffffffff'fffff000; /** * @brief Currently active level 4 page table, is used to ensure there is only ever one valid instance and it cannot @@ -17,7 +18,7 @@ namespace teachos::arch::memory::paging */ struct active_page_table { - typedef void (*function)(active_page_table * active_page_table); + typedef void (*function)(active_page_table & active_page_table); /** * @brief Creates a single instance of an active level 4 page table table and returns the created instance or @@ -53,6 +54,18 @@ namespace teachos::arch::memory::paging */ auto translate_huge_page(virtual_page page) -> std::optional; + /** + * @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained + * in. See https://www.felixcloutier.com/x86/invlpg for more information on the used x86 instruction. + * + * @param address Memory address, which will be used to determine the contained page and flush the TLB entry for + * that page. + */ + static auto invalidate_page_cache(virtual_address address) -> void + { + asm volatile("invlpg (%0)" ::"r"(address) : "memory"); + } + /** * @brief Maps a virtual page to a physical frame in the page table with the specified flags. * @@ -180,18 +193,6 @@ namespace teachos::arch::memory::paging */ active_page_table & operator=(active_page_table const &) = delete; - /** - * @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained - * in. See https://www.felixcloutier.com/x86/invlpg for more information on the used x86 instruction. - * - * @param address Memory address, which will be used to determine the contained page and flush the TLB entry for - * that page. - */ - static auto invalidate_page_cache(virtual_address address) -> void - { - asm volatile("invlpg (%0)" ::"r"(address) : "memory"); - } - /** * @brief Unmaps specific page at the current internal handle level. * diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 085344a..0583692 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -7,8 +7,16 @@ namespace teachos::arch::memory::paging { - auto with(inactive_page_table inactive_page_table, temporary_page temporary_page, active_page_table::function f, - active_page_table & active_page_table) -> void; + struct kernel_mapper + { + kernel_mapper(active_page_table & active_table); + + auto with(inactive_page_table inactive_page_table, temporary_page temporary_page, + active_page_table::function f) -> void; + + private: + active_page_table & active_table; + }; } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP -- cgit v1.2.3 From 1dd691e54ab30b70550ae6197ab252ebd0f8b223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 1 Nov 2024 15:18:02 +0000 Subject: Make page table handle public --- arch/x86_64/include/arch/memory/paging/active_page_table.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index e2c205b..56e0632 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -174,6 +174,7 @@ namespace teachos::arch::memory::paging invalidate_page_cache(page.start_address()); } + page_table_handle active_handle; ///< Underlying active level 4 page table private: /** * @brief Private constructor should only be used by create or get method, which ensures to create only ever one @@ -214,8 +215,6 @@ namespace teachos::arch::memory::paging entry.set_unused(); allocator.deallocate_frame(frame.value()); } - - page_table_handle active_handle; }; } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 38cda6bf579f7b09d06ad73c9f4ab893939727a2 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Fri, 1 Nov 2024 15:32:24 +0000 Subject: extract tlb methods and finish implementation of with --- .../arch/memory/paging/active_page_table.hpp | 22 +++++------------- arch/x86_64/include/arch/memory/paging/tlb.hpp | 26 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 17 deletions(-) create mode 100644 arch/x86_64/include/arch/memory/paging/tlb.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index e2c205b..30ae455 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -3,6 +3,7 @@ #include "arch/exception_handling/assert.hpp" #include "arch/memory/allocator/concept.hpp" +#include "arch/memory/paging/tlb.hpp" #include "arch/memory/paging/virtual_page.hpp" #include @@ -10,8 +11,6 @@ namespace teachos::arch::memory::paging { - std::size_t constexpr PAGE_TABLE_LEVEL_4_ADDRESS = 0xffffffff'fffff000; - /** * @brief Currently active level 4 page table, is used to ensure there is only ever one valid instance and it cannot * be copied or constructed again. @@ -54,18 +53,6 @@ namespace teachos::arch::memory::paging */ auto translate_huge_page(virtual_page page) -> std::optional; - /** - * @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained - * in. See https://www.felixcloutier.com/x86/invlpg for more information on the used x86 instruction. - * - * @param address Memory address, which will be used to determine the contained page and flush the TLB entry for - * that page. - */ - static auto invalidate_page_cache(virtual_address address) -> void - { - asm volatile("invlpg (%0)" ::"r"(address) : "memory"); - } - /** * @brief Maps a virtual page to a physical frame in the page table with the specified flags. * @@ -171,9 +158,12 @@ namespace teachos::arch::memory::paging break; } } - invalidate_page_cache(page.start_address()); + + tlb_flush(page.start_address()); } + page_table_handle active_handle; + private: /** * @brief Private constructor should only be used by create or get method, which ensures to create only ever one @@ -214,8 +204,6 @@ namespace teachos::arch::memory::paging entry.set_unused(); allocator.deallocate_frame(frame.value()); } - - page_table_handle active_handle; }; } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/include/arch/memory/paging/tlb.hpp b/arch/x86_64/include/arch/memory/paging/tlb.hpp new file mode 100644 index 0000000..e74eb74 --- /dev/null +++ b/arch/x86_64/include/arch/memory/paging/tlb.hpp @@ -0,0 +1,26 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_TLB_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_TLB_HPP + +#include "arch/memory/paging/virtual_page.hpp" + +namespace teachos::arch::memory::paging +{ + std::size_t constexpr PAGE_TABLE_LEVEL_4_ADDRESS = 0xffffffff'fffff000; + + /** + * @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained + * in. See https://www.felixcloutier.com/x86/invlpg for more information on the used x86 instruction. + * + * @param address Memory address, which will be used to determine the contained page and flush the TLB entry for + * that page. + */ + auto tlb_flush(virtual_address address) -> void; + + /** + * @brief Invalidates the translation lookaside buffer (TLB) entry for all page tables + */ + auto tlb_flush_all() -> void; + +} // namespace teachos::arch::memory::paging + +#endif \ No newline at end of file -- cgit v1.2.3 From 54cdc10862d95ccaf70def277946625d8c721113 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Fri, 1 Nov 2024 15:33:02 +0000 Subject: add spacing --- arch/x86_64/include/arch/memory/paging/active_page_table.hpp | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index 83624a9..8e80b51 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -163,6 +163,7 @@ namespace teachos::arch::memory::paging } page_table_handle active_handle; ///< Underlying active level 4 page table + private: /** * @brief Private constructor should only be used by create or get method, which ensures to create only ever one -- cgit v1.2.3 From d488a0709c5a2701482130a3d9c972c0b468a1d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 1 Nov 2024 15:34:03 +0000 Subject: Fix typo --- arch/x86_64/include/arch/memory/paging/tlb.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/tlb.hpp b/arch/x86_64/include/arch/memory/paging/tlb.hpp index e74eb74..1194720 100644 --- a/arch/x86_64/include/arch/memory/paging/tlb.hpp +++ b/arch/x86_64/include/arch/memory/paging/tlb.hpp @@ -23,4 +23,4 @@ namespace teachos::arch::memory::paging } // namespace teachos::arch::memory::paging -#endif \ No newline at end of file +#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_TLB_HPP -- cgit v1.2.3 From 5ffe7d69545bf098efdd70f105a5df83304b211a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 2 Nov 2024 11:49:38 +0000 Subject: Add physical frame iterator and continue implementing kernel mapping. --- .../arch/memory/allocator/area_frame_allocator.hpp | 2 +- .../arch/memory/allocator/physical_frame.hpp | 128 ++++++++++++++++++++- .../include/arch/memory/multiboot/reader.hpp | 9 +- .../arch/memory/paging/active_page_table.hpp | 2 - .../arch/memory/paging/inactive_page_table.hpp | 2 +- .../include/arch/memory/paging/kernel_mapper.hpp | 73 +++++++++++- arch/x86_64/include/arch/shared/container.hpp | 12 +- .../include/arch/shared/random_access_iterator.hpp | 11 +- 8 files changed, 213 insertions(+), 26 deletions(-) (limited to 'arch/x86_64/include') 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 4b6c2d4..f2b77f8 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 @@ -18,7 +18,7 @@ namespace teachos::arch::memory::allocator * * @param mem_info Structure containg all relevant information to map and allocate memory */ - area_frame_allocator(multiboot::memory_information mem_info); + area_frame_allocator(multiboot::memory_information const & mem_info); /** * @brief Allocate memory by finding and returning a free physical frame. diff --git a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp index 146e557..b95687c 100644 --- a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp +++ b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace teachos::arch::memory::allocator { @@ -16,6 +17,11 @@ namespace teachos::arch::memory::allocator */ struct physical_frame { + /** + * @brief Defaulted constructor. + */ + physical_frame() = default; + /** * @brief Constructor. * @@ -48,8 +54,126 @@ namespace teachos::arch::memory::allocator */ auto operator<=>(const physical_frame & 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. + std::size_t frame_number = + {}; ///< Index number of the current physical frame, used to distinguish it from other frames. + }; + + /** + * @brief Iterator for the frame number + */ + struct physical_frame_iterator + { + using iterator_category = std::random_access_iterator_tag; ///< Iterator category of this type. + using difference_type = std::ptrdiff_t; ///< Type when diving one instance of this iterator by another. + using value_type = physical_frame; ///< Underlying value pointed to by this iterator. + + /** + * @brief Defaulted constructor. + */ + physical_frame_iterator() = default; + + /** + * @brief Constructor. + * + * @param value Underlying value the iterator should point too + */ + explicit physical_frame_iterator(value_type value); + + /** + * @brief Dereferences the initally given pointer to its value. + * + * @return Reference to the value. + */ + auto operator*() -> value_type &; + + /** + * @brief Get underlying value, which is the intially passed pointer. + * + * @return Underlying value passed intially. + */ + auto operator->() -> value_type *; + + /** + * @brief Post increment operator. Returns a copy of the value. + * + * @return Copy of the incremented underlying address. + */ + auto operator++(int) -> physical_frame_iterator; + + /** + * @brief Pre increment operator. Returns a reference to the changed value. + * + * @return Reference to the incremented underlying address. + */ + auto operator++() -> physical_frame_iterator &; + + /** + * @brief Addition assignment operator. Returns a reference to the changed value. + * + * @param operand Value we want to add to the underlying address. + * @return Reference to the changed underlying address. + */ + auto operator+=(difference_type operand) -> physical_frame_iterator &; + + /** + * @brief Subtraction assignment operator. Returns a reference to the changed value. + * + * @param operand Value we want to subtract from the underlying address. + * @return Reference to the changed underlying address. + */ + auto operator-=(difference_type operand) -> physical_frame_iterator &; + + /** + * @brief Addition operator. Returns the changed value. + * + * @param operand Value we want to add to a copy of the underlying address. + * @return Copy of underlying address incremented by the given value. + */ + auto operator+(difference_type operand) const -> physical_frame_iterator; + + /** + * @brief Subtraction operator. Returns the changed value. + * + * @param operand Value we want to subtrcat from a copy of the underlying address. + * @return Copy of underlying address decremented by the given value. + */ + auto operator-(difference_type operand) const -> physical_frame_iterator; + + /** + * @brief Subtraction operator. Returns the size difference between two iterators. + * + * @param other Other iterator we want to substract the underlying address with ours. + * @return Size difference between the underlying address of this instance and the given iterator. + */ + auto operator-(const physical_frame_iterator & other) const -> difference_type; + + /** + * @brief Index operator overload. Returns a reference to the value at the given index. Simply returns the + * dereferenced underlying pointer incremented by the given index. + * + * @param index Index we want to access and get the value from. + * @return Reference to the value at the given index. + */ + auto operator[](difference_type index) const -> value_type; + + /** + * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators. + * + * @param other Other iterator to compare to. + * @return Whether both iterators point to the same underlying address in memory. + */ + auto operator==(physical_frame_iterator const & other) const -> bool = default; + + /** + * @brief Defaulted threeway comparsion operator. Simply compares the memory address of both iterators. + * + * @param other Other iterator to compare to. + * @return Whether the given iterator is smaller or larger than this iterator. + */ + auto operator<=>(physical_frame_iterator const & other) const -> std::strong_ordering = default; + + private: + value_type value = {}; ///< Underlying address the iterator is currently pointing too. }; } // namespace teachos::arch::memory::allocator diff --git a/arch/x86_64/include/arch/memory/multiboot/reader.hpp b/arch/x86_64/include/arch/memory/multiboot/reader.hpp index baa49c9..a5c4872 100644 --- a/arch/x86_64/include/arch/memory/multiboot/reader.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/reader.hpp @@ -1,6 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP #define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP +#include "arch/memory/multiboot/elf_symbols_section.hpp" #include "arch/memory/multiboot/memory_map.hpp" #include @@ -13,8 +14,12 @@ namespace teachos::arch::memory::multiboot */ struct memory_information { - std::size_t kernel_start; ///< Start address of the kernel code in memory. - std::size_t kernel_end; ///< End address of the kernel code in memory. + std::size_t kernel_start; ///< Start address of the kernel code in memory. + std::size_t kernel_end; ///< End address of the kernel code in memory. + elf_section_header_container::iterator + begin_kernel; ///< Iterator containing non-owning pointer to the first element of all kernel sections. + elf_section_header_container::iterator + end_kernel; ///< Iterator pointing to one past the last element of all kernel sections. std::size_t multiboot_start; ///< Start address of the multiboot code in memory. std::size_t multiboot_end; ///< End address of the multiboot code in memory. memory_area_container::iterator diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index 8e80b51..c183aff 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -17,8 +17,6 @@ namespace teachos::arch::memory::paging */ struct active_page_table { - typedef void (*function)(active_page_table & active_page_table); - /** * @brief Creates a single instance of an active level 4 page table table and returns the created instance or * alternatively returns the previously created instance instead. The instance is owned by this method and is diff --git a/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp b/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp index 62c196f..df3ba00 100644 --- a/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp @@ -9,7 +9,7 @@ namespace teachos::arch::memory::paging { struct inactive_page_table { - inactive_page_table(allocator::physical_frame frame, active_page_table active_page_table, + inactive_page_table(allocator::physical_frame frame, active_page_table & active_page_table, temporary_page temporary_page); allocator::physical_frame page_table_level_4_frame; diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 0583692..0e2411a 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -7,15 +7,80 @@ namespace teachos::arch::memory::paging { + namespace + { + std::size_t constexpr UNUSED_VIRTUAL_ADDRESS = 0xCAFEBABE; + } // namespace + + typedef shared::container frame_container; + + template struct kernel_mapper { - kernel_mapper(active_page_table & active_table); + kernel_mapper(T & allocator, multiboot::memory_information const & mem_info) + : allocator(allocator) + , mem_info(mem_info) + { + // Nothing to do + } - auto with(inactive_page_table inactive_page_table, temporary_page temporary_page, - active_page_table::function f) -> void; + auto remap_kernel() -> void + { + temporary_page temp_page{virtual_page{UNUSED_VIRTUAL_ADDRESS}, allocator}; + auto & active_table = active_page_table::create_or_get(); + auto const frame = allocator.allocate_frame(); + exception_handling::assert(frame.has_value(), + "[Kernel Mapper] Frame could not be allocated and therefore kernel not mapped"); + auto const inactive_table = inactive_page_table{frame.value(), active_table, temp_page}; + map_elf_sections(inactive_table, temp_page, active_table); + } private: - active_page_table & active_table; + auto map_elf_sections(inactive_page_table inactive_page_table, temporary_page temporary_page, + active_page_table & active_table) -> void + { + auto const backup = allocator::physical_frame::containing_address(PAGE_TABLE_LEVEL_4_ADDRESS); + auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); + + active_table.active_handle[511].set_entry(inactive_page_table.page_table_level_4_frame, + entry::PRESENT | entry::WRITABLE); + tlb_flush_all(); + map_kernel_sections(active_table); + + page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); + tlb_flush_all(); + temporary_page.unmap(active_table); + } + + auto map_kernel_sections(active_page_table & active_table) -> void + { + multiboot::elf_section_header_container sections{mem_info.begin_kernel, mem_info.end_kernel}; + for (auto const & section : sections) + { + if (!section.flags.contains_flags(multiboot::elf_section_flags::OCCUPIES_MEMORY)) + { + continue; + } + exception_handling::assert(section.virtual_address % allocator::PAGE_FRAME_SIZE == 0U, + "[Kernel Mapper] Section must be page aligned"); + auto const start_frame = allocator::physical_frame::containing_address(section.virtual_address); + auto const end_frame = + allocator::physical_frame::containing_address(section.virtual_address + section.section_size); + + allocator::physical_frame_iterator const begin{start_frame}; + allocator::physical_frame_iterator const end{end_frame}; + frame_container frames{begin, end}; + + for (auto frame : frames) + { + // TODO: Use actual elf section flags, convert from one to the other flag type. + active_table.identity_map(allocator, frame, entry::WRITABLE); + } + } + } + + T & allocator; + multiboot::memory_information const & mem_info; }; } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/include/arch/shared/container.hpp b/arch/x86_64/include/arch/shared/container.hpp index 8ea0d08..bc2a5f6 100644 --- a/arch/x86_64/include/arch/shared/container.hpp +++ b/arch/x86_64/include/arch/shared/container.hpp @@ -19,6 +19,11 @@ namespace teachos::arch::shared using iterator = T; ///< Iterators used by this container. using size_type = std::size_t; ///< Maximum size of this container. + /** + * @brief Defaulted constructor. + */ + container() = default; + /** * @brief Constructor. * @@ -29,8 +34,7 @@ namespace teachos::arch::shared : begin_itr(begin) , end_itr(end) { - exception_handling::assert(begin != iterator{}, "[Memory Area] Attempted to pass nullptr as begin iterator"); - exception_handling::assert(end != iterator{}, "[Memory Area] Attempted to pass nullptr as end iterator"); + // Nothing to do } /** @@ -65,8 +69,8 @@ namespace teachos::arch::shared auto empty() const -> bool { return size() == 0; } private: - iterator begin_itr; ///< Pointer to the first element of the given template type. - iterator end_itr; ///< Pointer to one pas the last element of the given template type. + iterator begin_itr = {}; ///< Pointer to the first element of the given template type. + iterator end_itr = {}; ///< Pointer to one pas the last element of the given template type. }; } // namespace teachos::arch::shared diff --git a/arch/x86_64/include/arch/shared/random_access_iterator.hpp b/arch/x86_64/include/arch/shared/random_access_iterator.hpp index 13deb68..b1a800c 100644 --- a/arch/x86_64/include/arch/shared/random_access_iterator.hpp +++ b/arch/x86_64/include/arch/shared/random_access_iterator.hpp @@ -26,8 +26,7 @@ namespace teachos::arch::shared /** * @brief Constructor. * - * @param p Underlying address the iterator should point too, ensure to not pass an invalid pointer or the - * constructor will halt execution. + * @param p Underlying address the iterator should point too. */ explicit random_access_iterator(value_type * p) : ptr(p) @@ -143,14 +142,6 @@ namespace teachos::arch::shared */ auto operator==(random_access_iterator const & other) const -> bool = default; - /** - * @brief Defaulted negated comparsion operator. Simply compares the memory address of both iterators. - * - * @param other Other iterator to compare to. - * @return Whether both iterators don't point to the same underlying address in memory. - */ - auto operator!=(random_access_iterator const & other) const -> bool = default; - /** * @brief Defaulted threeway comparsion operator. Simply compares the memory address of both iterators. * -- cgit v1.2.3 From 5ade8e0d5f190f2e439f81232b38b90c49c0cd1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 2 Nov 2024 12:38:22 +0000 Subject: Add comments and improve multiboot information struct usability. --- .../include/arch/memory/multiboot/reader.hpp | 17 +++--- .../arch/memory/paging/active_page_table.hpp | 4 +- .../arch/memory/paging/inactive_page_table.hpp | 14 ++++- .../include/arch/memory/paging/kernel_mapper.hpp | 63 ++++++++++++++++++---- 4 files changed, 73 insertions(+), 25 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot/reader.hpp b/arch/x86_64/include/arch/memory/multiboot/reader.hpp index a5c4872..9707757 100644 --- a/arch/x86_64/include/arch/memory/multiboot/reader.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/reader.hpp @@ -14,17 +14,12 @@ namespace teachos::arch::memory::multiboot */ struct memory_information { - std::size_t kernel_start; ///< Start address of the kernel code in memory. - std::size_t kernel_end; ///< End address of the kernel code in memory. - elf_section_header_container::iterator - begin_kernel; ///< Iterator containing non-owning pointer to the first element of all kernel sections. - elf_section_header_container::iterator - end_kernel; ///< Iterator pointing to one past the last element of all kernel sections. - std::size_t multiboot_start; ///< Start address of the multiboot code in memory. - std::size_t multiboot_end; ///< End address of the multiboot code in memory. - memory_area_container::iterator - begin_area; ///< Iterator containing non-owning pointer to the first element of all memory areas. - memory_area_container::iterator end_area; ///< Iterator pointing to one past the last element of all memory areas. + std::size_t kernel_start; ///< Start address of the kernel code in memory. + std::size_t kernel_end; ///< End address of the kernel code in memory. + elf_section_header_container sections; ///< Contains non-owning pointers to all kernel sections. + std::size_t multiboot_start; ///< Start address of the multiboot code in memory. + std::size_t multiboot_end; ///< End address of the multiboot code in memory. + memory_area_container areas; ///< Contains non-owning pointers to all memory areas. }; /** diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index c183aff..71f70b5 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -12,8 +12,8 @@ namespace teachos::arch::memory::paging { /** - * @brief Currently active level 4 page table, is used to ensure there is only ever one valid instance and it cannot - * be copied or constructed again. + * @brief Currently actively by the CPU used level 4 page table, is used to ensure there is only ever one valid + * instance and it cannot be copied or constructed again. */ struct active_page_table { diff --git a/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp b/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp index df3ba00..54a53f4 100644 --- a/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp @@ -7,12 +7,24 @@ namespace teachos::arch::memory::paging { + /** + * @brief By the CPU used level 4 page table. + */ struct inactive_page_table { + /** + * @brief Constructor. + * + * @param frame Frame that should be mapped as the level 4 page table. + * @param active_page_table Actual active page table that should be unmapped so we can map a new level 4 + * page table. + * @param temporary_page Temporary page that should be used to map the given frame as the new level 4 page + * table. + */ inactive_page_table(allocator::physical_frame frame, active_page_table & active_page_table, temporary_page temporary_page); - allocator::physical_frame page_table_level_4_frame; + allocator::physical_frame page_table_level_4_frame; ///< Temporary level 4 page table }; } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 0e2411a..5ee4ea8 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -14,9 +14,20 @@ namespace teachos::arch::memory::paging typedef shared::container frame_container; + /** + * @brief Kernel mapper that allows to remap the kernel elf sections in C++. + * + * @tparam T Contract the allocator that should be used to allocate frames for the remapping process has to fulfill. + */ template struct kernel_mapper { + /** + * @brief Constructor. + * + * @param allocator Allocator that should be used to allocate frames for the remapping process. + * @param mem_info Information about elf kernel sections required for remapping process. + */ kernel_mapper(T & allocator, multiboot::memory_information const & mem_info) : allocator(allocator) , mem_info(mem_info) @@ -24,6 +35,14 @@ namespace teachos::arch::memory::paging // Nothing to do } + /** + * @brief Remap the kernel, meaning we map the entire kernel and all of it's elf sections with the correct flags + * into memory and then replace the created mapping with the current one. + * + * @note We have to use a workaround with an + * inactive page table, that is not used by the CPU to ensure we are not changign memory that we are using. Because + * remapping active kernel memory in the kernel wouldn't work. + */ auto remap_kernel() -> void { temporary_page temp_page{virtual_page{UNUSED_VIRTUAL_ADDRESS}, allocator}; @@ -32,30 +51,51 @@ namespace teachos::arch::memory::paging exception_handling::assert(frame.has_value(), "[Kernel Mapper] Frame could not be allocated and therefore kernel not mapped"); auto const inactive_table = inactive_page_table{frame.value(), active_table, temp_page}; - map_elf_sections(inactive_table, temp_page, active_table); + remap_elf_kernel_sections(inactive_table, temp_page, active_table); } private: - auto map_elf_sections(inactive_page_table inactive_page_table, temporary_page temporary_page, - active_page_table & active_table) -> void + /** + * @brief Remaps the kernel elf sections. This is done with switching the current level 4 page table recursive + * mapping to any unmapped address in memory and then actually mapping the level 4 page table on that address. + * Once the remapping process is done we can restore the original recursive mapping with the complete remapped + * kernel. + * + * @note Because we change the entries we also have to ensure we flush the translation lookaside buffer, before we + * map the entries. + * + * @param inactive_table Level 4 page table we temporarily map the kernel into. + * @param temporary_page Temporary page that should be used for the mapping process and then + * unmapped once finished. + * @param active_table Active level 4 page table that has its recursive mapping overwritten temporarily and then + * restored once the process is finished. + */ + auto remap_elf_kernel_sections(inactive_page_table inactive_table, temporary_page & temporary_page, + active_page_table & active_table) -> void { auto const backup = allocator::physical_frame::containing_address(PAGE_TABLE_LEVEL_4_ADDRESS); auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); - active_table.active_handle[511].set_entry(inactive_page_table.page_table_level_4_frame, + active_table.active_handle[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); tlb_flush_all(); - map_kernel_sections(active_table); + map_elf_kernel_sections(active_table); page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); tlb_flush_all(); temporary_page.unmap(active_table); } - auto map_kernel_sections(active_page_table & active_table) -> void + /** + * @brief Maps the required entries according to every elf section and it's contained frames. Additionally each of + * thoose frames gets the correct entry flags according to elf section flags. + * + * @param active_table Active level 4 page table that should be used to map the required elf sections into entries. + * Has had its recursive mapping temporarily replaced and points to unmapped place in memory. + */ + auto map_elf_kernel_sections(active_page_table & active_table) -> void { - multiboot::elf_section_header_container sections{mem_info.begin_kernel, mem_info.end_kernel}; - for (auto const & section : sections) + for (auto const & section : mem_info.sections) { if (!section.flags.contains_flags(multiboot::elf_section_flags::OCCUPIES_MEMORY)) { @@ -71,7 +111,7 @@ namespace teachos::arch::memory::paging allocator::physical_frame_iterator const end{end_frame}; frame_container frames{begin, end}; - for (auto frame : frames) + for (auto const & frame : frames) { // TODO: Use actual elf section flags, convert from one to the other flag type. active_table.identity_map(allocator, frame, entry::WRITABLE); @@ -79,8 +119,9 @@ namespace teachos::arch::memory::paging } } - T & allocator; - multiboot::memory_information const & mem_info; + T & allocator; ///< Allocator that should be used to allocate frames for the mapping process. + multiboot::memory_information const & + mem_info; ///< Information about elf kernel sections required for remapping process. }; } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 4d76f412b071a05f0aae1d1307f2b58cb2778569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 2 Nov 2024 14:08:55 +0000 Subject: Attempt to fix crashes --- .../arch/memory/allocator/tiny_frame_allocator.hpp | 19 +++++++++++--- .../arch/memory/paging/active_page_table.hpp | 2 +- .../include/arch/memory/paging/kernel_mapper.hpp | 30 +++++++++++----------- .../include/arch/memory/paging/temporary_page.hpp | 7 ++--- 4 files changed, 36 insertions(+), 22 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp index e55b376..b8ed506 100644 --- a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp @@ -9,6 +9,11 @@ namespace teachos::arch::memory::allocator { + namespace + { + uint8_t constexpr TINY_ALLOCATOR_FRAMES_COUNT = 3U; + } + /** * @brief Allocates memory using memory areas read from the multiboot2 information pointer. */ @@ -23,9 +28,16 @@ namespace teachos::arch::memory::allocator * entries *when a new page table is required. */ tiny_frame_allocator(area_frame_allocator & allocator) - : frames{allocator.allocate_frame(), allocator.allocate_frame(), allocator.allocate_frame()} + : frames{} { - // Nothing to do + for (auto & frame : frames) + { + auto allocated = allocator.allocate_frame(); + if (allocated.has_value()) + { + frame.emplace(allocated.value()); + } + } } /** @@ -47,7 +59,8 @@ namespace teachos::arch::memory::allocator auto deallocate_frame(physical_frame physical_frame) -> void; private: - std::array, 3U> frames = {}; + std::array, TINY_ALLOCATOR_FRAMES_COUNT> frames = + {}; ///< Container that holds the frames allocated by another allocator. }; } // namespace teachos::arch::memory::allocator diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index 71f70b5..5140c3d 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -128,7 +128,7 @@ namespace teachos::arch::memory::paging "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); auto current_handle = active_handle; - std::array handles{current_handle, current_handle, current_handle, current_handle}; + std::array handles{current_handle, current_handle, current_handle}; for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) { diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 5ee4ea8..a7ae3aa 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -16,21 +16,16 @@ namespace teachos::arch::memory::paging /** * @brief Kernel mapper that allows to remap the kernel elf sections in C++. - * - * @tparam T Contract the allocator that should be used to allocate frames for the remapping process has to fulfill. */ - template struct kernel_mapper { /** * @brief Constructor. * - * @param allocator Allocator that should be used to allocate frames for the remapping process. * @param mem_info Information about elf kernel sections required for remapping process. */ - kernel_mapper(T & allocator, multiboot::memory_information const & mem_info) - : allocator(allocator) - , mem_info(mem_info) + kernel_mapper(multiboot::memory_information const & mem_info) + : mem_info(mem_info) { // Nothing to do } @@ -42,16 +37,22 @@ namespace teachos::arch::memory::paging * @note We have to use a workaround with an * inactive page table, that is not used by the CPU to ensure we are not changign memory that we are using. Because * remapping active kernel memory in the kernel wouldn't work. + * + * @tparam T Contract the allocator that should be used to allocate frames for the remapping process has to fulfill. + * + * @param allocator Allocator that should be used to allocate frames for the remapping process. */ - auto remap_kernel() -> void + template + auto remap_kernel(T & allocator) -> void { - temporary_page temp_page{virtual_page{UNUSED_VIRTUAL_ADDRESS}, allocator}; + virtual_page temporary_address{UNUSED_VIRTUAL_ADDRESS}; + temporary_page temporary_page{temporary_address, allocator}; auto & active_table = active_page_table::create_or_get(); auto const frame = allocator.allocate_frame(); exception_handling::assert(frame.has_value(), "[Kernel Mapper] Frame could not be allocated and therefore kernel not mapped"); - auto const inactive_table = inactive_page_table{frame.value(), active_table, temp_page}; - remap_elf_kernel_sections(inactive_table, temp_page, active_table); + inactive_page_table inactive_table{frame.value(), active_table, temporary_page}; + remap_elf_kernel_sections(inactive_table, temporary_page, active_table); } private: @@ -79,7 +80,7 @@ namespace teachos::arch::memory::paging active_table.active_handle[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); tlb_flush_all(); - map_elf_kernel_sections(active_table); + map_elf_kernel_sections(temporary_page, active_table); page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); tlb_flush_all(); @@ -93,7 +94,7 @@ namespace teachos::arch::memory::paging * @param active_table Active level 4 page table that should be used to map the required elf sections into entries. * Has had its recursive mapping temporarily replaced and points to unmapped place in memory. */ - auto map_elf_kernel_sections(active_page_table & active_table) -> void + auto map_elf_kernel_sections(temporary_page & temporary_page, active_page_table & active_table) -> void { for (auto const & section : mem_info.sections) { @@ -114,12 +115,11 @@ namespace teachos::arch::memory::paging for (auto const & frame : frames) { // TODO: Use actual elf section flags, convert from one to the other flag type. - active_table.identity_map(allocator, frame, entry::WRITABLE); + active_table.identity_map(temporary_page.allocator, frame, entry::WRITABLE); } } } - T & allocator; ///< Allocator that should be used to allocate frames for the mapping process. multiboot::memory_information const & mem_info; ///< Information about elf kernel sections required for remapping process. }; diff --git a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp index 0cadc29..6b3bcb6 100644 --- a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp @@ -51,6 +51,10 @@ namespace teachos::arch::memory::paging */ auto map_table_frame(allocator::physical_frame frame, active_page_table & active_table) -> page_table_handle; + // TODO: Better way to do this? + virtual_page page; + allocator::tiny_frame_allocator allocator; + private: /** * @brief Map the temporary page to a frame. @@ -60,9 +64,6 @@ namespace teachos::arch::memory::paging * @return The virtual address of the page. */ auto map_to_frame(allocator::physical_frame frame, active_page_table & active_table) -> virtual_address; - - virtual_page page; - allocator::tiny_frame_allocator allocator; }; } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From d4b1b8a85212f07df47217fe13d86956c7eb064f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 3 Nov 2024 10:47:33 +0000 Subject: Use passed allocator in inactive page instead of tiny. --- .../include/arch/memory/paging/kernel_mapper.hpp | 25 +++++++++++----------- .../include/arch/memory/paging/temporary_page.hpp | 9 ++++---- 2 files changed, 17 insertions(+), 17 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index a7ae3aa..d7365a0 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -16,16 +16,21 @@ namespace teachos::arch::memory::paging /** * @brief Kernel mapper that allows to remap the kernel elf sections in C++. + * + * @tparam T Contract the allocator that should be used to allocate frames for the remapping process has to fulfill. */ + template struct kernel_mapper { /** * @brief Constructor. * + * @param allocator Allocator that should be used to allocate frames for the remapping process. * @param mem_info Information about elf kernel sections required for remapping process. */ - kernel_mapper(multiboot::memory_information const & mem_info) - : mem_info(mem_info) + kernel_mapper(T & allocator, multiboot::memory_information const & mem_info) + : allocator(allocator) + , mem_info(mem_info) { // Nothing to do } @@ -37,13 +42,8 @@ namespace teachos::arch::memory::paging * @note We have to use a workaround with an * inactive page table, that is not used by the CPU to ensure we are not changign memory that we are using. Because * remapping active kernel memory in the kernel wouldn't work. - * - * @tparam T Contract the allocator that should be used to allocate frames for the remapping process has to fulfill. - * - * @param allocator Allocator that should be used to allocate frames for the remapping process. */ - template - auto remap_kernel(T & allocator) -> void + auto remap_kernel() -> void { virtual_page temporary_address{UNUSED_VIRTUAL_ADDRESS}; temporary_page temporary_page{temporary_address, allocator}; @@ -80,11 +80,11 @@ namespace teachos::arch::memory::paging active_table.active_handle[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); tlb_flush_all(); - map_elf_kernel_sections(temporary_page, active_table); + map_elf_kernel_sections(active_table); page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); tlb_flush_all(); - temporary_page.unmap(active_table); + temporary_page.unmap_page(active_table); } /** @@ -94,7 +94,7 @@ namespace teachos::arch::memory::paging * @param active_table Active level 4 page table that should be used to map the required elf sections into entries. * Has had its recursive mapping temporarily replaced and points to unmapped place in memory. */ - auto map_elf_kernel_sections(temporary_page & temporary_page, active_page_table & active_table) -> void + auto map_elf_kernel_sections(active_page_table & active_table) -> void { for (auto const & section : mem_info.sections) { @@ -115,11 +115,12 @@ namespace teachos::arch::memory::paging for (auto const & frame : frames) { // TODO: Use actual elf section flags, convert from one to the other flag type. - active_table.identity_map(temporary_page.allocator, frame, entry::WRITABLE); + active_table.identity_map(allocator, frame, entry::WRITABLE); } } } + T & allocator; multiboot::memory_information const & mem_info; ///< Information about elf kernel sections required for remapping process. }; diff --git a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp index 6b3bcb6..8b49894 100644 --- a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp @@ -40,7 +40,7 @@ namespace teachos::arch::memory::paging * * @param active_table The current active page table. */ - auto unmap(active_page_table & active_table) -> void; + auto unmap_page(active_page_table & active_table) -> void; /** * @brief Map the temporary page to a frame. @@ -51,10 +51,6 @@ namespace teachos::arch::memory::paging */ auto map_table_frame(allocator::physical_frame frame, active_page_table & active_table) -> page_table_handle; - // TODO: Better way to do this? - virtual_page page; - allocator::tiny_frame_allocator allocator; - private: /** * @brief Map the temporary page to a frame. @@ -64,6 +60,9 @@ namespace teachos::arch::memory::paging * @return The virtual address of the page. */ auto map_to_frame(allocator::physical_frame frame, active_page_table & active_table) -> virtual_address; + + virtual_page page; ///< Underlying virtual page we want to temporarily map a level 4 page table into. + allocator::tiny_frame_allocator allocator; ///< Allocator that should be used to map the temporary page. }; } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 9292814545ab5df5aa69d4f75a6d9230f3e03f5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 3 Nov 2024 11:03:34 +0000 Subject: Move possible implementation into cpp --- .../include/arch/memory/allocator/tiny_frame_allocator.hpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp index b8ed506..a96b743 100644 --- a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp @@ -27,18 +27,7 @@ namespace teachos::arch::memory::allocator * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate * entries *when a new page table is required. */ - tiny_frame_allocator(area_frame_allocator & allocator) - : frames{} - { - for (auto & frame : frames) - { - auto allocated = allocator.allocate_frame(); - if (allocated.has_value()) - { - frame.emplace(allocated.value()); - } - } - } + tiny_frame_allocator(area_frame_allocator & allocator); /** * @brief Allocate memory by finding and returning one of the three free physical frames. -- cgit v1.2.3 From be546b091795e740e9dd4c35fce6453fafe0319c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 3 Nov 2024 11:56:46 +0000 Subject: Make member variables private again. --- arch/x86_64/include/arch/memory/paging/active_page_table.hpp | 12 ++++++++++-- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 3 +-- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index 5140c3d..0561420 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -26,6 +26,14 @@ namespace teachos::arch::memory::paging */ static auto create_or_get() -> active_page_table &; + /** + * @brief Index operator overload to access specific mutable entry directy of the level 4 page table. + * + * @param index Index of the entry we want to access and only read. + * @return Entry at the given table index. + */ + auto operator[](std::size_t index) -> entry &; + /** * @brief Translates virtual address into corresponding physical address. Calls translate_page under the hood. * @@ -160,8 +168,6 @@ namespace teachos::arch::memory::paging tlb_flush(page.start_address()); } - page_table_handle active_handle; ///< Underlying active level 4 page table - private: /** * @brief Private constructor should only be used by create or get method, which ensures to create only ever one @@ -202,6 +208,8 @@ namespace teachos::arch::memory::paging entry.set_unused(); allocator.deallocate_frame(frame.value()); } + + page_table_handle active_handle; ///< Underlying active level 4 page table }; } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index d7365a0..ede027c 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -77,8 +77,7 @@ namespace teachos::arch::memory::paging auto const backup = allocator::physical_frame::containing_address(PAGE_TABLE_LEVEL_4_ADDRESS); auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); - active_table.active_handle[511].set_entry(inactive_table.page_table_level_4_frame, - entry::PRESENT | entry::WRITABLE); + active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); tlb_flush_all(); map_elf_kernel_sections(active_table); -- cgit v1.2.3 From 67be3c58bef94fece14d4e3a79f3559649e9a74c Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 3 Nov 2024 12:12:41 +0000 Subject: rename member and use correct address --- .../arch/memory/multiboot/elf_symbols_section.hpp | 8 ++++---- .../x86_64/include/arch/memory/paging/kernel_mapper.hpp | 17 ++++++++++++----- arch/x86_64/include/arch/memory/paging/tlb.hpp | 2 +- 3 files changed, 17 insertions(+), 10 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp index c9989ae..e29590d 100644 --- a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp @@ -120,10 +120,10 @@ namespace teachos::arch::memory::multiboot uint32_t name_table_index; ///< Index into the section header string table, specifies the name of the section. elf_section_type type; ///< Categorizes the sections content and semantics. elf_section_flags flags; ///< 1-bit flgas that describe section attributes. - uint64_t virtual_address; ///< If section appears in memory image of a process, gives address at which the sections - ///< first byte should reside, otherwise 0. - uint64_t file_offset; ///< Offset from the beginning of the file to the first byte in the section. SHT_NOBITS - ///< contains the conceptual placement instead (because it occupies no space in the file). + uint64_t physical_address; ///< If section appears in memory image of a process, gives address at which the + ///< sections first byte should reside, otherwise 0. + uint64_t file_offset; ///< Offset from the beginning of the file to the first byte in the section. SHT_NOBITS + ///< contains the conceptual placement instead (because it occupies no space in the file). uint64_t section_size; ///< Complete section size in bytes, SHT_NOBITS may have non-zero value but will always ///< occupy no space in the file. uint32_t other_section; ///< Section header table index link, behaviour varies on type diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index d7365a0..84f0471 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -57,7 +57,9 @@ namespace teachos::arch::memory::paging private: /** - * @brief Remaps the kernel elf sections. This is done with switching the current level 4 page table recursive + * @brief Remaps the kernel elf sections. + * + * This is done with switching the current level 4 page table recursive * mapping to any unmapped address in memory and then actually mapping the level 4 page table on that address. * Once the remapping process is done we can restore the original recursive mapping with the complete remapped * kernel. @@ -74,11 +76,16 @@ namespace teachos::arch::memory::paging auto remap_elf_kernel_sections(inactive_page_table inactive_table, temporary_page & temporary_page, active_page_table & active_table) -> void { - auto const backup = allocator::physical_frame::containing_address(PAGE_TABLE_LEVEL_4_ADDRESS); + auto physical_address = active_table.translate_address(PAGE_TABLE_LEVEL_4_ADDRESS); + exception_handling::assert(!physical_address.has_value(), + "[Kernel Mapper] Physical address for active table not mapped"); + + auto const backup = allocator::physical_frame::containing_address(physical_address.value()); auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); active_table.active_handle[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); + tlb_flush_all(); map_elf_kernel_sections(active_table); @@ -102,11 +109,11 @@ namespace teachos::arch::memory::paging { continue; } - exception_handling::assert(section.virtual_address % allocator::PAGE_FRAME_SIZE == 0U, + exception_handling::assert(section.physical_address % allocator::PAGE_FRAME_SIZE == 0U, "[Kernel Mapper] Section must be page aligned"); - auto const start_frame = allocator::physical_frame::containing_address(section.virtual_address); + auto const start_frame = allocator::physical_frame::containing_address(section.physical_address); auto const end_frame = - allocator::physical_frame::containing_address(section.virtual_address + section.section_size); + allocator::physical_frame::containing_address(section.physical_address + section.section_size); allocator::physical_frame_iterator const begin{start_frame}; allocator::physical_frame_iterator const end{end_frame}; diff --git a/arch/x86_64/include/arch/memory/paging/tlb.hpp b/arch/x86_64/include/arch/memory/paging/tlb.hpp index 1194720..85c4152 100644 --- a/arch/x86_64/include/arch/memory/paging/tlb.hpp +++ b/arch/x86_64/include/arch/memory/paging/tlb.hpp @@ -5,7 +5,7 @@ namespace teachos::arch::memory::paging { - std::size_t constexpr PAGE_TABLE_LEVEL_4_ADDRESS = 0xffffffff'fffff000; + virtual_address constexpr PAGE_TABLE_LEVEL_4_ADDRESS = 0xffffffff'fffff000; /** * @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained -- cgit v1.2.3 From 756ef3a6d6aa61656dddbfea97482c8698807e39 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 3 Nov 2024 12:15:43 +0000 Subject: fix assert --- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index f06c4e2..3931db3 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -77,7 +77,7 @@ namespace teachos::arch::memory::paging active_page_table & active_table) -> void { auto physical_address = active_table.translate_address(PAGE_TABLE_LEVEL_4_ADDRESS); - exception_handling::assert(!physical_address.has_value(), + exception_handling::assert(physical_address.has_value(), "[Kernel Mapper] Physical address for active table not mapped"); auto const backup = allocator::physical_frame::containing_address(physical_address.value()); -- cgit v1.2.3 From 380bc85d1a4fdbef102132c726ef2ac7ac6355da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 3 Nov 2024 12:20:21 +0000 Subject: Make constructor constexpr for basic page and frame types --- arch/x86_64/include/arch/memory/allocator/physical_frame.hpp | 8 ++++++-- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 5 ++--- arch/x86_64/include/arch/memory/paging/virtual_page.hpp | 6 +++++- 3 files changed, 13 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp index b95687c..89e3cf8 100644 --- a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp +++ b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp @@ -20,14 +20,18 @@ namespace teachos::arch::memory::allocator /** * @brief Defaulted constructor. */ - physical_frame() = default; + constexpr physical_frame() = default; /** * @brief Constructor. * * @param frame_number Index number that should be assigned to this physical frame. */ - explicit physical_frame(std::size_t frame_number); + 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. diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 3931db3..c62a02e 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -9,7 +9,7 @@ namespace teachos::arch::memory::paging { namespace { - std::size_t constexpr UNUSED_VIRTUAL_ADDRESS = 0xCAFEBABE; + virtual_page constexpr UNUSED_VIRTUAL_PAGE{0xCAFEBABE}; } // namespace typedef shared::container frame_container; @@ -45,8 +45,7 @@ namespace teachos::arch::memory::paging */ auto remap_kernel() -> void { - virtual_page temporary_address{UNUSED_VIRTUAL_ADDRESS}; - temporary_page temporary_page{temporary_address, allocator}; + temporary_page temporary_page{UNUSED_VIRTUAL_PAGE, allocator}; auto & active_table = active_page_table::create_or_get(); auto const frame = allocator.allocate_frame(); exception_handling::assert(frame.has_value(), diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index 8c5613d..c319af2 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -22,7 +22,11 @@ namespace teachos::arch::memory::paging * * @param page_number Index number of the current virtual page, used to distinguish it from other pages. */ - explicit virtual_page(std::size_t page_number); + explicit constexpr virtual_page(std::size_t page_number) + : page_number(page_number) + { + // Nothing to do + } /** * @brief Returns the virtual page the given address is contained in. -- cgit v1.2.3 From 74c53bed107b87f064484b926d8ed02018eb3a3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 3 Nov 2024 13:23:40 +0000 Subject: Adjust comment --- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 3 ++- arch/x86_64/include/arch/memory/paging/temporary_page.hpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index c62a02e..f30ca24 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -75,7 +75,7 @@ namespace teachos::arch::memory::paging auto remap_elf_kernel_sections(inactive_page_table inactive_table, temporary_page & temporary_page, active_page_table & active_table) -> void { - auto physical_address = active_table.translate_address(PAGE_TABLE_LEVEL_4_ADDRESS); + auto const physical_address = active_table.translate_address(PAGE_TABLE_LEVEL_4_ADDRESS); exception_handling::assert(physical_address.has_value(), "[Kernel Mapper] Physical address for active table not mapped"); @@ -100,6 +100,7 @@ namespace teachos::arch::memory::paging */ auto map_elf_kernel_sections(active_page_table & active_table) -> void { + exception_handling::assert(!mem_info.sections.empty(), "[Kernel Mapper] Kernel elf sections empty"); for (auto const & section : mem_info.sections) { if (!section.flags.contains_flags(multiboot::elf_section_flags::OCCUPIES_MEMORY)) diff --git a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp index 8b49894..b93a375 100644 --- a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp @@ -61,7 +61,7 @@ namespace teachos::arch::memory::paging */ auto map_to_frame(allocator::physical_frame frame, active_page_table & active_table) -> virtual_address; - virtual_page page; ///< Underlying virtual page we want to temporarily map a level 4 page table into. + virtual_page page; ///< Underlying virtual page we want to temporarily map. allocator::tiny_frame_allocator allocator; ///< Allocator that should be used to map the temporary page. }; } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From db70018fc76800dd56b4421be797bffd00d7619d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 3 Nov 2024 13:52:22 +0000 Subject: Convert elf section flags to entry flags --- .../include/arch/memory/paging/kernel_mapper.hpp | 4 ++-- .../x86_64/include/arch/memory/paging/page_entry.hpp | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index f30ca24..54ec682 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -116,11 +116,11 @@ namespace teachos::arch::memory::paging allocator::physical_frame_iterator const begin{start_frame}; allocator::physical_frame_iterator const end{end_frame}; frame_container frames{begin, end}; + entry entry{section.flags}; for (auto const & frame : frames) { - // TODO: Use actual elf section flags, convert from one to the other flag type. - active_table.identity_map(allocator, frame, entry::WRITABLE); + active_table.identity_map(allocator, frame, entry.get_flags()); } } } diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index 5959801..ab9659d 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -2,6 +2,7 @@ #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_ENTRY_HPP #include "arch/memory/allocator/physical_frame.hpp" +#include "arch/memory/multiboot/elf_symbols_section.hpp" #include #include @@ -47,6 +48,18 @@ namespace teachos::arch::memory::paging */ explicit entry(uint64_t flags); + /** + * @brief Converts the given elf section flags into the corresponding correct entry flags. + * + * @note Enables us to set the correct flags on a entry depending on which elf section it is contained in. For + * example entries of .text sections should be executable and read only or entries of .data sections should be + * writable but not executable. + * + * @param elf_flags Elf section flags we want to convert into entry flags. + * @return Entry that has the corresponding bit flags set. + */ + explicit entry(multiboot::elf_section_flags elf_flags); + /** * @brief Whether the current page is unused, meaning the underlying std::bitset is 0. * @@ -86,6 +99,13 @@ namespace teachos::arch::memory::paging */ auto contains_flags(std::bitset<64U> other) const -> bool; + /** + * @brief Extracts only the flags from the underlying entry and ignores all bits that contain the physical address. + * + * @return Extracted entry flags, without the physical address. + */ + auto get_flags() -> std::bitset<64U>; + private: std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 9 - 11 and 52 - 62 can be ///< freely used for additional flags by the operating system. -- cgit v1.2.3 From 95d8c279bf945c99ef207c12de3ab6a2bc14f380 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 3 Nov 2024 14:57:06 +0000 Subject: construct virtual_page using containing_address --- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 54ec682..2dd0387 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -9,7 +9,7 @@ namespace teachos::arch::memory::paging { namespace { - virtual_page constexpr UNUSED_VIRTUAL_PAGE{0xCAFEBABE}; + virtual_page UNUSED_VIRTUAL_PAGE = virtual_page::containing_address(0xCAFEBABE); } // namespace typedef shared::container frame_container; -- cgit v1.2.3 From 162bea11c7a4f1854cde53920b4c14b4eadf539d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 4 Nov 2024 12:13:44 +0000 Subject: WIP attempt to fix crashes --- .../arch/memory/allocator/physical_frame.hpp | 105 ++++------------ .../arch/memory/multiboot/elf_symbols_section.hpp | 6 +- .../include/arch/memory/multiboot/memory_map.hpp | 2 +- .../include/arch/memory/paging/kernel_mapper.hpp | 25 ++-- arch/x86_64/include/arch/shared/container.hpp | 5 +- .../include/arch/shared/random_access_iterator.hpp | 138 ++++++++++++++------- 6 files changed, 134 insertions(+), 147 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp index 89e3cf8..43a22a2 100644 --- a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp +++ b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp @@ -1,6 +1,9 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP #define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP +#include "arch/shared/container.hpp" +#include "arch/shared/random_access_iterator.hpp" + #include #include #include @@ -48,68 +51,19 @@ namespace teachos::arch::memory::allocator */ auto start_address() const -> physical_address; - /** - * @brief Defaulted equals operator. - */ - auto operator==(const physical_frame & other) const -> bool = default; - - /** - * @brief Defaulted three-way comparsion operator. - */ - auto operator<=>(const physical_frame & 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. - }; - - /** - * @brief Iterator for the frame number - */ - struct physical_frame_iterator - { - using iterator_category = std::random_access_iterator_tag; ///< Iterator category of this type. - using difference_type = std::ptrdiff_t; ///< Type when diving one instance of this iterator by another. - using value_type = physical_frame; ///< Underlying value pointed to by this iterator. - - /** - * @brief Defaulted constructor. - */ - physical_frame_iterator() = default; - - /** - * @brief Constructor. - * - * @param value Underlying value the iterator should point too - */ - explicit physical_frame_iterator(value_type value); - - /** - * @brief Dereferences the initally given pointer to its value. - * - * @return Reference to the value. - */ - auto operator*() -> value_type &; - - /** - * @brief Get underlying value, which is the intially passed pointer. - * - * @return Underlying value passed intially. - */ - auto operator->() -> value_type *; - /** * @brief Post increment operator. Returns a copy of the value. * * @return Copy of the incremented underlying address. */ - auto operator++(int) -> physical_frame_iterator; + auto operator++(int) -> physical_frame; /** * @brief Pre increment operator. Returns a reference to the changed value. * * @return Reference to the incremented underlying address. */ - auto operator++() -> physical_frame_iterator &; + auto operator++() -> physical_frame &; /** * @brief Addition assignment operator. Returns a reference to the changed value. @@ -117,7 +71,7 @@ namespace teachos::arch::memory::allocator * @param operand Value we want to add to the underlying address. * @return Reference to the changed underlying address. */ - auto operator+=(difference_type operand) -> physical_frame_iterator &; + auto operator+=(std::size_t operand) -> physical_frame &; /** * @brief Subtraction assignment operator. Returns a reference to the changed value. @@ -125,23 +79,21 @@ namespace teachos::arch::memory::allocator * @param operand Value we want to subtract from the underlying address. * @return Reference to the changed underlying address. */ - auto operator-=(difference_type operand) -> physical_frame_iterator &; + auto operator-=(std::size_t operand) -> physical_frame &; /** - * @brief Addition operator. Returns the changed value. + * @brief Post increment operator. Returns a copy of the value. * - * @param operand Value we want to add to a copy of the underlying address. - * @return Copy of underlying address incremented by the given value. + * @return Copy of the incremented underlying address. */ - auto operator+(difference_type operand) const -> physical_frame_iterator; + auto operator+(std::size_t operand) const -> physical_frame; /** - * @brief Subtraction operator. Returns the changed value. + * @brief Pre increment operator. Returns a reference to the changed value. * - * @param operand Value we want to subtrcat from a copy of the underlying address. - * @return Copy of underlying address decremented by the given value. + * @return Reference to the incremented underlying address. */ - auto operator-(difference_type operand) const -> physical_frame_iterator; + auto operator-(std::size_t operand) const -> physical_frame; /** * @brief Subtraction operator. Returns the size difference between two iterators. @@ -149,36 +101,23 @@ namespace teachos::arch::memory::allocator * @param other Other iterator we want to substract the underlying address with ours. * @return Size difference between the underlying address of this instance and the given iterator. */ - auto operator-(const physical_frame_iterator & other) const -> difference_type; - - /** - * @brief Index operator overload. Returns a reference to the value at the given index. Simply returns the - * dereferenced underlying pointer incremented by the given index. - * - * @param index Index we want to access and get the value from. - * @return Reference to the value at the given index. - */ - auto operator[](difference_type index) const -> value_type; + auto operator-(physical_frame const & other) const -> std::size_t; /** - * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators. - * - * @param other Other iterator to compare to. - * @return Whether both iterators point to the same underlying address in memory. + * @brief Defaulted equals operator. */ - auto operator==(physical_frame_iterator const & other) const -> bool = default; + auto operator==(physical_frame const & other) const -> bool = default; /** - * @brief Defaulted threeway comparsion operator. Simply compares the memory address of both iterators. - * - * @param other Other iterator to compare to. - * @return Whether the given iterator is smaller or larger than this iterator. + * @brief Defaulted three-way comparsion operator. */ - auto operator<=>(physical_frame_iterator const & other) const -> std::strong_ordering = default; + auto operator<=>(physical_frame const & other) const -> std::partial_ordering = default; - private: - value_type value = {}; ///< Underlying address the iterator is currently pointing too. + std::size_t frame_number = + {}; ///< Index number of the current physical frame, used to distinguish it from other frames. }; + + typedef shared::container> frame_container; } // namespace teachos::arch::memory::allocator #endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp index e29590d..6227fc9 100644 --- a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp @@ -122,8 +122,8 @@ namespace teachos::arch::memory::multiboot elf_section_flags flags; ///< 1-bit flgas that describe section attributes. uint64_t physical_address; ///< If section appears in memory image of a process, gives address at which the ///< sections first byte should reside, otherwise 0. - uint64_t file_offset; ///< Offset from the beginning of the file to the first byte in the section. SHT_NOBITS - ///< contains the conceptual placement instead (because it occupies no space in the file). + uint64_t file_offset; ///< Offset from the beginning of the file to the first byte in the section. SHT_NOBITS + ///< contains the conceptual placement instead (because it occupies no space in the file). uint64_t section_size; ///< Complete section size in bytes, SHT_NOBITS may have non-zero value but will always ///< occupy no space in the file. uint32_t other_section; ///< Section header table index link, behaviour varies on type @@ -162,7 +162,7 @@ namespace teachos::arch::memory::multiboot ///< contained in the section, to ensure byte alignment is actually 4 byte. }; - typedef shared::container> elf_section_header_container; + typedef shared::container> elf_section_header_container; } // namespace teachos::arch::memory::multiboot #endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp index 910eecb..ccd5cf0 100644 --- a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp @@ -46,7 +46,7 @@ namespace teachos::arch::memory::multiboot struct memory_area entries; ///< Specific memory regions. }; - typedef shared::container> memory_area_container; + typedef shared::container> memory_area_container; } // namespace teachos::arch::memory::multiboot #endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 2dd0387..d301c91 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -9,11 +9,9 @@ namespace teachos::arch::memory::paging { namespace { - virtual_page UNUSED_VIRTUAL_PAGE = virtual_page::containing_address(0xCAFEBABE); + virtual_page constexpr UNUSED_VIRTUAL_PAGE(0xCAFEBABE); } // namespace - typedef shared::container frame_container; - /** * @brief Kernel mapper that allows to remap the kernel elf sections in C++. * @@ -103,20 +101,23 @@ namespace teachos::arch::memory::paging exception_handling::assert(!mem_info.sections.empty(), "[Kernel Mapper] Kernel elf sections empty"); for (auto const & section : mem_info.sections) { - if (!section.flags.contains_flags(multiboot::elf_section_flags::OCCUPIES_MEMORY)) + if (!section->flags.contains_flags(multiboot::elf_section_flags::OCCUPIES_MEMORY)) { continue; } - exception_handling::assert(section.physical_address % allocator::PAGE_FRAME_SIZE == 0U, + exception_handling::assert(section->physical_address % allocator::PAGE_FRAME_SIZE == 0U, "[Kernel Mapper] Section must be page aligned"); - auto const start_frame = allocator::physical_frame::containing_address(section.physical_address); - auto const end_frame = - allocator::physical_frame::containing_address(section.physical_address + section.section_size); + auto const start_frame = allocator::physical_frame::containing_address(section->physical_address); + // End address is exclusive, so that it is not part of the section anymore (one past the last frame of this + // section). But end frame would now point to the actual last frame and not one past the last frame, therefore + // we increment by one to get one past the last frame of this section. + auto end_frame = + ++(allocator::physical_frame::containing_address(section->physical_address + section->section_size - 1)); - allocator::physical_frame_iterator const begin{start_frame}; - allocator::physical_frame_iterator const end{end_frame}; - frame_container frames{begin, end}; - entry entry{section.flags}; + allocator::frame_container::iterator const begin{start_frame}; + allocator::frame_container::iterator const end{end_frame}; + allocator::frame_container frames{begin, end}; + entry entry{section->flags}; for (auto const & frame : frames) { diff --git a/arch/x86_64/include/arch/shared/container.hpp b/arch/x86_64/include/arch/shared/container.hpp index bc2a5f6..9b4192e 100644 --- a/arch/x86_64/include/arch/shared/container.hpp +++ b/arch/x86_64/include/arch/shared/container.hpp @@ -1,12 +1,13 @@ #ifndef TEACHOS_ARCH_X86_64_SHARED_CONTAINER_HPP #define TEACHOS_ARCH_X86_64_SHARED_CONTAINER_HPP -#include "arch/exception_handling/assert.hpp" - #include namespace teachos::arch::shared { + template + concept Iterator = std::contiguous_iterator; + /** * @brief Read-only container for given template type, that allow to easily use this container instance in C++20 * ranges calls. diff --git a/arch/x86_64/include/arch/shared/random_access_iterator.hpp b/arch/x86_64/include/arch/shared/random_access_iterator.hpp index b1a800c..69617f3 100644 --- a/arch/x86_64/include/arch/shared/random_access_iterator.hpp +++ b/arch/x86_64/include/arch/shared/random_access_iterator.hpp @@ -5,18 +5,25 @@ namespace teachos::arch::shared { + template + concept Iterable = std::incrementable && std::three_way_comparable && std::indirectly_readable; + /** - * @brief Generic random access iterator for given template type. Can be a nullptr, ensure to check when using this - * iterator. Allows to easily use this iterator instance in algorithm calls. + * @brief Generic random access iterator for given template type. Allows any value that Allows to easily use this + * iterator instance in algorithm calls. * * @tparam T Value the iterator points too. */ - template + template struct random_access_iterator { - using iterator_category = std::random_access_iterator_tag; ///< Iterator category of this type. - using difference_type = std::ptrdiff_t; ///< Type when diving one instance of this iterator by another. - using value_type = T; ///< Underlying value pointed to by this iterator. + using iterator_category = std::contiguous_iterator_tag; ///< Iterator category of this type. + using difference_type = std::ptrdiff_t; ///< Type when diving one instance of this iterator by another. + using value_type = T; ///< Underlying value pointed to by this iterator. + using reference_type = value_type &; ///< Reference to value returned by dereference * operation. + using pointer_type = value_type *; ///< Pointer to value returned by arrow -> operation. + using const_reference_type = value_type const &; ///< Reference to value returned by const dereference * operation. + using const_pointer_type = value_type const *; ///< Pointer to value returned by const arrow -> operation. /** * @brief Defaulted constructor. @@ -26,124 +33,162 @@ namespace teachos::arch::shared /** * @brief Constructor. * - * @param p Underlying address the iterator should point too. + * @param value Underlying value the iterator should point too and increment or decrement. */ - explicit random_access_iterator(value_type * p) - : ptr(p) + explicit random_access_iterator(value_type value) + : value(value) { // Nothing to do } /** - * @brief Dereferences the initally given pointer to its value. + * @brief Gets a reference to the underlying value. * * @return Reference to the value. */ - auto operator*() const -> value_type & { return *ptr; } + auto operator*() -> reference_type { return value; } /** - * @brief Get underlying value, which is the intially passed pointer. + * @brief Gets a pointer to the underlying value. * * @return Underlying value passed intially. */ - auto operator->() const -> value_type * { return ptr; } + auto operator->() -> pointer_type { return &value; } /** - * @brief Post increment operator. Returns a copy of the value. + * @brief Gets a const reference to the underlying value. * - * @return Copy of the incremented underlying address. + * @return Reference to the value. */ - auto operator++(int) -> random_access_iterator + auto operator*() const -> const_reference_type { return value; } + + /** + * @brief Gets a const pointer to the underlying value. + * + * @return Underlying value passed intially. + */ + auto operator->() const -> const_pointer_type { return &value; } + + /** + * @brief Pre decrement operator. Returns a reference to the changed value. + * + * @return Reference to the decrement underlying value. + */ + auto operator--() -> random_access_iterator & { - random_access_iterator const old_value = *this; - ++ptr; - return old_value; + --value; + return *this; } /** * @brief Pre increment operator. Returns a reference to the changed value. * - * @return Reference to the incremented underlying address. + * @return Reference to the incremented underlying value. */ auto operator++() -> random_access_iterator & { - ++ptr; + ++value; return *this; } + /** + * @brief Post decrement operator. Returns a copy of the value. + * + * @return Copy of the decremented underlying value. + */ + auto operator--(int) -> random_access_iterator + { + auto const old_value = *this; + --value; + return old_value; + } + + /** + * @brief Post increment operator. Returns a copy of the value. + * + * @return Copy of the incremented underlying value. + */ + auto operator++(int) -> random_access_iterator + { + auto const old_value = *this; + ++value; + return old_value; + } + /** * @brief Addition assignment operator. Returns a reference to the changed value. * - * @param value Value we want to add to the underlying address. - * @return Reference to the changed underlying address. + * @param operand Value we want to add to the underlying value the iterator is pointing too. + * @return Reference to the changed underlying value. */ - auto operator+=(difference_type value) -> random_access_iterator & + auto operator+=(difference_type operand) -> random_access_iterator & { - ptr += value; + value += operand; return *this; } /** * @brief Subtraction assignment operator. Returns a reference to the changed value. * - * @param value Value we want to subtract from the underlying address. - * @return Reference to the changed underlying address. + * @param operand Value we want to subtract from the underlying value the iterator is pointing too. + * @return Reference to the changed underlying value. */ - auto operator-=(difference_type value) -> random_access_iterator & + auto operator-=(difference_type operand) -> random_access_iterator & { - ptr -= value; + value -= operand; return *this; } /** * @brief Addition operator. Returns the changed value. * - * @param value Value we want to add to a copy of the underlying address. - * @return Copy of underlying address incremented by the given value. + * @param operand Value we want to add to a copy of the underlying value the iterator is pointing too. + * @return Copy of underlying value incremented by the given value. */ - auto operator+(difference_type value) const -> random_access_iterator + auto operator+(difference_type operand) const -> random_access_iterator { - return random_access_iterator{ptr + value}; + return random_access_iterator{value + operand}; } /** * @brief Subtraction operator. Returns the changed value. * - * @param value Value we want to subtrcat from a copy of the underlying address. - * @return Copy of underlying address decremented by the given value. + * @param operand Value we want to subtract from a copy of the underlying value the iterator is pointing too. + * @return Copy of underlying value decremented by the given value. */ - auto operator-(difference_type value) const -> random_access_iterator + auto operator-(difference_type operand) const -> random_access_iterator { - return random_access_iterator{ptr - value}; + return random_access_iterator{value - operand}; } /** * @brief Subtraction operator. Returns the size difference between two iterators. * - * @param other Other iterator we want to substract the underlying address with ours. - * @return Size difference between the underlying address of this instance and the given iterator. + * @param other Other iterator we want to substract the underlying value with ours. + * @return Size difference between the underlying value of this instance and the given iterator. */ - auto operator-(const random_access_iterator & other) const -> difference_type { return ptr - other.ptr; } + auto operator-(random_access_iterator const & other) const -> difference_type { return value - other.value; } /** * @brief Index operator overload. Returns a reference to the value at the given index. Simply returns the - * dereferenced underlying pointer incremented by the given index. + * underlying value the iterator is pointing too incremented by the given index. * * @param index Index we want to access and get the value from. * @return Reference to the value at the given index. */ - auto operator[](difference_type index) const -> value_type & { return *(ptr + index); } + auto operator[](difference_type index) const -> value_type const & { return value + index; } /** - * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators. + * @brief Defaulted comparsion operator. Forwards to the comparsion operator of the given template type. * * @param other Other iterator to compare to. - * @return Whether both iterators point to the same underlying address in memory. + * @return Whether both iterators point to the same underlying value in memory. */ auto operator==(random_access_iterator const & other) const -> bool = default; /** - * @brief Defaulted threeway comparsion operator. Simply compares the memory address of both iterators. + * @brief Defaulted threeway comparsion operator. Forwards to the threeway comparsion operator of the given + * template type. * * @param other Other iterator to compare to. * @return Whether the given iterator is smaller or larger than this iterator. @@ -151,7 +196,8 @@ namespace teachos::arch::shared auto operator<=>(random_access_iterator const & other) const -> std::strong_ordering = default; private: - value_type * ptr = {}; ///< Underlying address the iterator is currently pointing too. + value_type value = + {}; ///< Underlying value the iterator is currently pointing too and should increment or decrement. }; } // namespace teachos::arch::shared -- cgit v1.2.3 From 30466aeb3da181c21bd451f32c1ff97e53a55dbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 4 Nov 2024 13:29:03 +0000 Subject: Use more concepts and seperate iterator implementations --- .../arch/memory/allocator/physical_frame.hpp | 42 +---- .../arch/memory/multiboot/elf_symbols_section.hpp | 4 +- .../include/arch/memory/multiboot/memory_map.hpp | 4 +- .../include/arch/memory/paging/kernel_mapper.hpp | 10 +- arch/x86_64/include/arch/shared/container.hpp | 10 +- .../arch/shared/contiguous_pointer_iterator.hpp | 189 +++++++++++++++++++ .../include/arch/shared/forward_value_iterator.hpp | 109 +++++++++++ .../include/arch/shared/random_access_iterator.hpp | 204 --------------------- 8 files changed, 316 insertions(+), 256 deletions(-) create mode 100644 arch/x86_64/include/arch/shared/contiguous_pointer_iterator.hpp create mode 100644 arch/x86_64/include/arch/shared/forward_value_iterator.hpp delete mode 100644 arch/x86_64/include/arch/shared/random_access_iterator.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp index 43a22a2..a39517a 100644 --- a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp +++ b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp @@ -2,7 +2,7 @@ #define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP #include "arch/shared/container.hpp" -#include "arch/shared/random_access_iterator.hpp" +#include "arch/shared/forward_value_iterator.hpp" #include #include @@ -65,44 +65,6 @@ namespace teachos::arch::memory::allocator */ auto operator++() -> physical_frame &; - /** - * @brief Addition assignment operator. Returns a reference to the changed value. - * - * @param operand Value we want to add to the underlying address. - * @return Reference to the changed underlying address. - */ - auto operator+=(std::size_t operand) -> physical_frame &; - - /** - * @brief Subtraction assignment operator. Returns a reference to the changed value. - * - * @param operand Value we want to subtract from the underlying address. - * @return Reference to the changed underlying address. - */ - auto operator-=(std::size_t operand) -> physical_frame &; - - /** - * @brief Post increment operator. Returns a copy of the value. - * - * @return Copy of the incremented underlying address. - */ - auto operator+(std::size_t operand) const -> physical_frame; - - /** - * @brief Pre increment operator. Returns a reference to the changed value. - * - * @return Reference to the incremented underlying address. - */ - auto operator-(std::size_t operand) const -> physical_frame; - - /** - * @brief Subtraction operator. Returns the size difference between two iterators. - * - * @param other Other iterator we want to substract the underlying address with ours. - * @return Size difference between the underlying address of this instance and the given iterator. - */ - auto operator-(physical_frame const & other) const -> std::size_t; - /** * @brief Defaulted equals operator. */ @@ -117,7 +79,7 @@ namespace teachos::arch::memory::allocator {}; ///< Index number of the current physical frame, used to distinguish it from other frames. }; - typedef shared::container> frame_container; + typedef shared::container> frame_container; } // namespace teachos::arch::memory::allocator #endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp index 6227fc9..549839a 100644 --- a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp @@ -3,7 +3,7 @@ #include "arch/memory/multiboot/info.hpp" #include "arch/shared/container.hpp" -#include "arch/shared/random_access_iterator.hpp" +#include "arch/shared/contiguous_pointer_iterator.hpp" #include #include @@ -162,7 +162,7 @@ namespace teachos::arch::memory::multiboot ///< contained in the section, to ensure byte alignment is actually 4 byte. }; - typedef shared::container> elf_section_header_container; + typedef shared::container> elf_section_header_container; } // namespace teachos::arch::memory::multiboot #endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp index ccd5cf0..413f5a1 100644 --- a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp @@ -3,7 +3,7 @@ #include "arch/memory/multiboot/info.hpp" #include "arch/shared/container.hpp" -#include "arch/shared/random_access_iterator.hpp" +#include "arch/shared/contiguous_pointer_iterator.hpp" #include @@ -46,7 +46,7 @@ namespace teachos::arch::memory::multiboot struct memory_area entries; ///< Specific memory regions. }; - typedef shared::container> memory_area_container; + typedef shared::container> memory_area_container; } // namespace teachos::arch::memory::multiboot #endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index d301c91..2eb3c4a 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -101,23 +101,23 @@ namespace teachos::arch::memory::paging exception_handling::assert(!mem_info.sections.empty(), "[Kernel Mapper] Kernel elf sections empty"); for (auto const & section : mem_info.sections) { - if (!section->flags.contains_flags(multiboot::elf_section_flags::OCCUPIES_MEMORY)) + if (!section.flags.contains_flags(multiboot::elf_section_flags::OCCUPIES_MEMORY)) { continue; } - exception_handling::assert(section->physical_address % allocator::PAGE_FRAME_SIZE == 0U, + exception_handling::assert(section.physical_address % allocator::PAGE_FRAME_SIZE == 0U, "[Kernel Mapper] Section must be page aligned"); - auto const start_frame = allocator::physical_frame::containing_address(section->physical_address); + auto const start_frame = allocator::physical_frame::containing_address(section.physical_address); // End address is exclusive, so that it is not part of the section anymore (one past the last frame of this // section). But end frame would now point to the actual last frame and not one past the last frame, therefore // we increment by one to get one past the last frame of this section. auto end_frame = - ++(allocator::physical_frame::containing_address(section->physical_address + section->section_size - 1)); + ++(allocator::physical_frame::containing_address(section.physical_address + section.section_size - 1)); allocator::frame_container::iterator const begin{start_frame}; allocator::frame_container::iterator const end{end_frame}; allocator::frame_container frames{begin, end}; - entry entry{section->flags}; + entry entry{section.flags}; for (auto const & frame : frames) { diff --git a/arch/x86_64/include/arch/shared/container.hpp b/arch/x86_64/include/arch/shared/container.hpp index 9b4192e..b335e72 100644 --- a/arch/x86_64/include/arch/shared/container.hpp +++ b/arch/x86_64/include/arch/shared/container.hpp @@ -5,16 +5,20 @@ namespace teachos::arch::shared { + /** + * @brief Minimal iterator concept required for usage in container + */ template - concept Iterator = std::contiguous_iterator; + concept Iterator = std::forward_iterator; /** * @brief Read-only container for given template type, that allow to easily use this container instance in C++20 * ranges calls. * - * @tparam T Iterator the container uses to signal the start and end of it's data. + * @tparam T Iterator the container uses to signal the start and end of it's data, has to atleast be a simple forward + * iterator. */ - template + template struct container { using iterator = T; ///< Iterators used by this container. diff --git a/arch/x86_64/include/arch/shared/contiguous_pointer_iterator.hpp b/arch/x86_64/include/arch/shared/contiguous_pointer_iterator.hpp new file mode 100644 index 0000000..7d5019a --- /dev/null +++ b/arch/x86_64/include/arch/shared/contiguous_pointer_iterator.hpp @@ -0,0 +1,189 @@ +#ifndef TEACHOS_ARCH_X86_64_SHARED_CONTIGUOUS_POINTER_ITERATOR_HPP +#define TEACHOS_ARCH_X86_64_SHARED_CONTIGUOUS_POINTER_ITERATOR_HPP + +#include + +namespace teachos::arch::shared +{ + /** + * @brief Generic contiguous iterator for given template type. Allows to easily use this iterator instance in + * algorithm calls. + * + * @note Allows any value that is contained in an array in memory, which is a block of contiguous memory. This is the + * case because we assume we can simply increment or decrement the pointer address to get the next valid instance of + * the given value type. + * + * @tparam T Value the iterator points too. + */ + template + struct contiguous_pointer_iterator + { + using iterator_category = std::contiguous_iterator_tag; ///< Iterator category of this type. + using difference_type = std::ptrdiff_t; ///< Type when diving one instance of this iterator by another. + using value_type = T; ///< Underlying value pointed to by this iterator. + using reference_type = value_type &; ///< Reference to value returned by dereference * operation. + using pointer_type = value_type *; ///< Pointer to value returned by arrow -> operation. + + /** + * @brief Defaulted constructor. + */ + contiguous_pointer_iterator() = default; + + /** + * @brief Constructor. + * + * @param p Underlying address the iterator should point too. + */ + explicit contiguous_pointer_iterator(value_type * p) + : ptr(p) + { + // Nothing to do + } + + /** + * @brief Dereferences the initally given pointer to its value. + * + * @return Reference to the value. + */ + auto operator*() const -> reference_type { return *ptr; } + + /** + * @brief Get underlying value, which is the intially passed pointer. + * + * @return Pointer to the underlying value passed intially. + */ + auto operator->() const -> pointer_type { return ptr; } + + /** + * @brief Pre decrement operator. Returns a reference to the changed address. + * + * @return Reference to the decremented underlying address. + */ + auto operator--() -> contiguous_pointer_iterator & + { + contiguous_pointer_iterator const old_value = *this; + ++ptr; + return old_value; + } + + /** + * @brief Pre increment operator. Returns a reference to the changed address. + * + * @return Reference to the incremented underlying address. + */ + auto operator++() -> contiguous_pointer_iterator & + { + ++ptr; + return *this; + } + + /** + * @brief Post decrement operator. Returns a copy of the address. + * + * @return Copy of the decremented underlying address. + */ + auto operator--(int) -> contiguous_pointer_iterator + { + auto const old_value = *this; + --ptr; + return old_value; + } + + /** + * @brief Post increment operator. Returns a copy of the address. + * + * @return Copy of the incremented underlying address. + */ + auto operator++(int) -> contiguous_pointer_iterator + { + auto const old_value = *this; + ++ptr; + return old_value; + } + + /** + * @brief Addition assignment operator. Returns a reference to the changed address. + * + * @param value Value we want to add to the underlying address. + * @return Reference to the changed underlying address. + */ + auto operator+=(difference_type value) -> contiguous_pointer_iterator & + { + ptr += value; + return *this; + } + + /** + * @brief Subtraction assignment operator. Returns a reference to the changed address. + * + * @param value Value we want to subtract from the underlying address. + * @return Reference to the changed underlying address. + */ + auto operator-=(difference_type value) -> contiguous_pointer_iterator & + { + ptr -= value; + return *this; + } + + /** + * @brief Addition operator. Returns the changed address. + * + * @param value Value we want to add to a copy of the underlying address. + * @return Copy of underlying address incremented by the given value. + */ + auto operator+(difference_type value) const -> contiguous_pointer_iterator + { + return contiguous_pointer_iterator{ptr + value}; + } + + /** + * @brief Subtraction operator. Returns the changed address. + * + * @param value Value we want to subtrcat from a copy of the underlying address. + * @return Copy of underlying address decremented by the given value. + */ + auto operator-(difference_type value) const -> contiguous_pointer_iterator + { + return contiguous_pointer_iterator{ptr - value}; + } + + /** + * @brief Subtraction operator. Returns the size difference between two iterators. + * + * @param other Other iterator we want to substract the underlying address with ours. + * @return Size difference between the underlying address of this instance and the given iterator. + */ + auto operator-(const contiguous_pointer_iterator & other) const -> difference_type { return ptr - other.ptr; } + + /** + * @brief Index operator overload. Returns a reference to the value at the given index. Simply returns the + * dereferenced underlying pointer incremented by the given index. + * + * @param index Index we want to access and get the value from. + * @return Reference to the value at the given index. + */ + auto operator[](difference_type index) const -> value_type & { return *(ptr + index); } + + /** + * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators. + * + * @param other Other iterator to compare to. + * @return Whether both iterators point to the same underlying address in memory. + */ + auto operator==(contiguous_pointer_iterator const & other) const -> bool = default; + + /** + * @brief Defaulted threeway comparsion operator. Simply compares the memory address of both iterators. + * + * @param other Other iterator to compare to. + * @return Whether the given iterator is smaller or larger than this iterator. + */ + auto operator<=>(contiguous_pointer_iterator const & other) const -> std::strong_ordering = default; + + private: + pointer_type ptr = + {}; ///< Underlying value the iterator is currently pointing too and should increment or decrement. + }; +} // namespace teachos::arch::shared + +#endif // TEACHOS_ARCH_X86_64_SHARED_CONTIGUOUS_POINTER_ITERATOR_HPP diff --git a/arch/x86_64/include/arch/shared/forward_value_iterator.hpp b/arch/x86_64/include/arch/shared/forward_value_iterator.hpp new file mode 100644 index 0000000..a84d291 --- /dev/null +++ b/arch/x86_64/include/arch/shared/forward_value_iterator.hpp @@ -0,0 +1,109 @@ +#ifndef TEACHOS_ARCH_X86_64_SHARED_FORWARD_VALUE_ITERATOR_HPP +#define TEACHOS_ARCH_X86_64_SHARED_FORWARD_VALUE_ITERATOR_HPP + +#include + +namespace teachos::arch::shared +{ + /** + * @brief Concept for a type to have a post and prefix increment operator, that returns the correct type. + */ + template + concept Incrementable = requires(T t) { + { ++t } -> std::same_as; + { t++ } -> std::same_as; + }; + + /** + * @brief Iterable concept for the forward value iterator, meaning the type itself is incrementable and comparable. + */ + template + concept Iterable = std::regular && Incrementable; + + /** + * @brief Generic forward iterator for given template type. Allows to easily use this iterator + * instance in algorithm calls. + * + * @note Allows any value that itself can be incremented until we have reached the end, does not interact with the + * address of the value in any way. + * + * @tparam T Value the iterator contains. + */ + template + struct forward_value_iterator + { + using iterator_category = std::forward_iterator_tag; ///< Iterator category of this type. + using difference_type = std::ptrdiff_t; ///< Type when diving one instance of this iterator by another. + using value_type = T; ///< Underlying value contained by this iterator. + using const_reference_type = + value_type const &; ///< Constant reference to value returned by dereference * operation. + using const_pointer_type = value_type const *; ///< Constant pointer to value returned by arrow -> operation. + + /** + * @brief Defaulted constructor. + */ + forward_value_iterator() = default; + + /** + * @brief Constructor. + * + * @param value Underlying value the iterator contains. + */ + explicit forward_value_iterator(value_type value) + : value(value) + { + // Nothing to do + } + + /** + * @brief Returns the initally given value. + * + * @return Reference to the value. + */ + auto operator*() const -> const_reference_type { return value; } + + /** + * @brief Gets pointer to the underlying value passed intially. + * + * @return Pointer to the underlying value passed intially. + */ + auto operator->() const -> const_pointer_type { return &value; } + + /** + * @brief Pre increment operator. Returns a reference to the changed value. + * + * @return Reference to the incremented underlying value. + */ + auto operator++() -> forward_value_iterator & + { + ++value; + return *this; + } + + /** + * @brief Post increment operator. Returns a copy of the value. + * + * @return Copy of the incremented underlying value. + */ + auto operator++(int) -> forward_value_iterator + { + auto const old_value = *this; + ++value; + return old_value; + } + + /** + * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators. + * + * @param other Other iterator to compare to. + * @return Whether both iterators point to the same underlying address in memory. + */ + auto operator==(forward_value_iterator const & other) const -> bool = default; + + private: + value_type value = + {}; ///< Underlying value the iterator is currently pointing too and should increment or decrement. + }; +} // namespace teachos::arch::shared + +#endif // TEACHOS_ARCH_X86_64_SHARED_FORWARD_VALUE_ITERATOR_HPP diff --git a/arch/x86_64/include/arch/shared/random_access_iterator.hpp b/arch/x86_64/include/arch/shared/random_access_iterator.hpp deleted file mode 100644 index 69617f3..0000000 --- a/arch/x86_64/include/arch/shared/random_access_iterator.hpp +++ /dev/null @@ -1,204 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_SHARED_RANDOM_ACCESS_ITERATOR_HPP -#define TEACHOS_ARCH_X86_64_SHARED_RANDOM_ACCESS_ITERATOR_HPP - -#include - -namespace teachos::arch::shared -{ - template - concept Iterable = std::incrementable && std::three_way_comparable && std::indirectly_readable; - - /** - * @brief Generic random access iterator for given template type. Allows any value that Allows to easily use this - * iterator instance in algorithm calls. - * - * @tparam T Value the iterator points too. - */ - template - struct random_access_iterator - { - using iterator_category = std::contiguous_iterator_tag; ///< Iterator category of this type. - using difference_type = std::ptrdiff_t; ///< Type when diving one instance of this iterator by another. - using value_type = T; ///< Underlying value pointed to by this iterator. - using reference_type = value_type &; ///< Reference to value returned by dereference * operation. - using pointer_type = value_type *; ///< Pointer to value returned by arrow -> operation. - using const_reference_type = value_type const &; ///< Reference to value returned by const dereference * operation. - using const_pointer_type = value_type const *; ///< Pointer to value returned by const arrow -> operation. - - /** - * @brief Defaulted constructor. - */ - random_access_iterator() = default; - - /** - * @brief Constructor. - * - * @param value Underlying value the iterator should point too and increment or decrement. - */ - explicit random_access_iterator(value_type value) - : value(value) - { - // Nothing to do - } - - /** - * @brief Gets a reference to the underlying value. - * - * @return Reference to the value. - */ - auto operator*() -> reference_type { return value; } - - /** - * @brief Gets a pointer to the underlying value. - * - * @return Underlying value passed intially. - */ - auto operator->() -> pointer_type { return &value; } - - /** - * @brief Gets a const reference to the underlying value. - * - * @return Reference to the value. - */ - auto operator*() const -> const_reference_type { return value; } - - /** - * @brief Gets a const pointer to the underlying value. - * - * @return Underlying value passed intially. - */ - auto operator->() const -> const_pointer_type { return &value; } - - /** - * @brief Pre decrement operator. Returns a reference to the changed value. - * - * @return Reference to the decrement underlying value. - */ - auto operator--() -> random_access_iterator & - { - --value; - return *this; - } - - /** - * @brief Pre increment operator. Returns a reference to the changed value. - * - * @return Reference to the incremented underlying value. - */ - auto operator++() -> random_access_iterator & - { - ++value; - return *this; - } - - /** - * @brief Post decrement operator. Returns a copy of the value. - * - * @return Copy of the decremented underlying value. - */ - auto operator--(int) -> random_access_iterator - { - auto const old_value = *this; - --value; - return old_value; - } - - /** - * @brief Post increment operator. Returns a copy of the value. - * - * @return Copy of the incremented underlying value. - */ - auto operator++(int) -> random_access_iterator - { - auto const old_value = *this; - ++value; - return old_value; - } - - /** - * @brief Addition assignment operator. Returns a reference to the changed value. - * - * @param operand Value we want to add to the underlying value the iterator is pointing too. - * @return Reference to the changed underlying value. - */ - auto operator+=(difference_type operand) -> random_access_iterator & - { - value += operand; - return *this; - } - - /** - * @brief Subtraction assignment operator. Returns a reference to the changed value. - * - * @param operand Value we want to subtract from the underlying value the iterator is pointing too. - * @return Reference to the changed underlying value. - */ - auto operator-=(difference_type operand) -> random_access_iterator & - { - value -= operand; - return *this; - } - - /** - * @brief Addition operator. Returns the changed value. - * - * @param operand Value we want to add to a copy of the underlying value the iterator is pointing too. - * @return Copy of underlying value incremented by the given value. - */ - auto operator+(difference_type operand) const -> random_access_iterator - { - return random_access_iterator{value + operand}; - } - - /** - * @brief Subtraction operator. Returns the changed value. - * - * @param operand Value we want to subtract from a copy of the underlying value the iterator is pointing too. - * @return Copy of underlying value decremented by the given value. - */ - auto operator-(difference_type operand) const -> random_access_iterator - { - return random_access_iterator{value - operand}; - } - - /** - * @brief Subtraction operator. Returns the size difference between two iterators. - * - * @param other Other iterator we want to substract the underlying value with ours. - * @return Size difference between the underlying value of this instance and the given iterator. - */ - auto operator-(random_access_iterator const & other) const -> difference_type { return value - other.value; } - - /** - * @brief Index operator overload. Returns a reference to the value at the given index. Simply returns the - * underlying value the iterator is pointing too incremented by the given index. - * - * @param index Index we want to access and get the value from. - * @return Reference to the value at the given index. - */ - auto operator[](difference_type index) const -> value_type const & { return value + index; } - - /** - * @brief Defaulted comparsion operator. Forwards to the comparsion operator of the given template type. - * - * @param other Other iterator to compare to. - * @return Whether both iterators point to the same underlying value in memory. - */ - auto operator==(random_access_iterator const & other) const -> bool = default; - - /** - * @brief Defaulted threeway comparsion operator. Forwards to the threeway comparsion operator of the given - * template type. - * - * @param other Other iterator to compare to. - * @return Whether the given iterator is smaller or larger than this iterator. - */ - auto operator<=>(random_access_iterator const & other) const -> std::strong_ordering = default; - - private: - value_type value = - {}; ///< Underlying value the iterator is currently pointing too and should increment or decrement. - }; -} // namespace teachos::arch::shared - -#endif // TEACHOS_ARCH_X86_64_SHARED_RANDOM_ACCESS_ITERATOR_HPP -- cgit v1.2.3 From c887e22cd7827ae53fd3eab6f5af41969cdd616c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 4 Nov 2024 13:55:22 +0000 Subject: Use auto where possible --- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 2eb3c4a..05a1cf2 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -80,6 +80,8 @@ namespace teachos::arch::memory::paging auto const backup = allocator::physical_frame::containing_address(physical_address.value()); auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); + // TODO: Page Table Level 4 is invalid, all entries point to non-existent memory :( + active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); tlb_flush_all(); map_elf_kernel_sections(active_table); -- cgit v1.2.3 From 77b50aa74e404a7af4b17d05613b21c8e5cd6f49 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 5 Nov 2024 09:54:48 +0000 Subject: remove variable --- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 05a1cf2..23a18dd 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -7,11 +7,6 @@ namespace teachos::arch::memory::paging { - namespace - { - virtual_page constexpr UNUSED_VIRTUAL_PAGE(0xCAFEBABE); - } // namespace - /** * @brief Kernel mapper that allows to remap the kernel elf sections in C++. * @@ -43,7 +38,7 @@ namespace teachos::arch::memory::paging */ auto remap_kernel() -> void { - temporary_page temporary_page{UNUSED_VIRTUAL_PAGE, allocator}; + temporary_page temporary_page{virtual_page{0xCAFEBABE}, allocator}; auto & active_table = active_page_table::create_or_get(); auto const frame = allocator.allocate_frame(); exception_handling::assert(frame.has_value(), -- cgit v1.2.3 From dc80a11864444cae275e9e7be9ae120a92433034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 5 Nov 2024 09:58:05 +0000 Subject: Move tlb into seperate subfolder and create cr3 header for reading and writing. --- arch/x86_64/include/arch/boot/pointers.hpp | 2 +- arch/x86_64/include/arch/memory/cpu/cr3.hpp | 27 ++++++++++++++++++++++ arch/x86_64/include/arch/memory/cpu/tlb.hpp | 26 +++++++++++++++++++++ .../arch/memory/paging/active_page_table.hpp | 4 ++-- .../include/arch/memory/paging/kernel_mapper.hpp | 15 +++++++++--- arch/x86_64/include/arch/memory/paging/tlb.hpp | 26 --------------------- 6 files changed, 68 insertions(+), 32 deletions(-) create mode 100644 arch/x86_64/include/arch/memory/cpu/cr3.hpp create mode 100644 arch/x86_64/include/arch/memory/cpu/tlb.hpp delete mode 100644 arch/x86_64/include/arch/memory/paging/tlb.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index 25800f4..1172443 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -8,4 +8,4 @@ namespace teachos::arch::boot extern "C" size_t const multiboot_information_pointer; } // namespace teachos::arch::boot -#endif +#endif // TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP diff --git a/arch/x86_64/include/arch/memory/cpu/cr3.hpp b/arch/x86_64/include/arch/memory/cpu/cr3.hpp new file mode 100644 index 0000000..51d5055 --- /dev/null +++ b/arch/x86_64/include/arch/memory/cpu/cr3.hpp @@ -0,0 +1,27 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP + +#include "arch/memory/allocator/physical_frame.hpp" + +namespace teachos::arch::memory::cpu +{ + /** + * @brief Reads the value of the cr3 register. + * + * @note The cr3 register value represents the physical address of the level 4 page table used for paging in the + * system. Therefore reading this value allows to access the level 4 page table directly. Instead of over the virtual + * address 0xffffffff'fffff000, which then has to be first translated into a physical address. + * + * @return Physical address the level 4 page table is located at. + */ + auto read_cr3_register() -> allocator::physical_address; + + /** + * @brief Writes the given value into the cr3 register. + * + * @param new_p4_table_address Physical address the newly kernel mapped level 4 page table is located at. + */ + auto write_cr3_register(allocator::physical_address new_p4_table_address) -> void; +} // namespace teachos::arch::memory::cpu + +#endif // TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP diff --git a/arch/x86_64/include/arch/memory/cpu/tlb.hpp b/arch/x86_64/include/arch/memory/cpu/tlb.hpp new file mode 100644 index 0000000..dc7ec61 --- /dev/null +++ b/arch/x86_64/include/arch/memory/cpu/tlb.hpp @@ -0,0 +1,26 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_CPU_TLB_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_CPU_TLB_HPP + +#include "arch/memory/paging/virtual_page.hpp" + +namespace teachos::arch::memory::cpu +{ + paging::virtual_address constexpr PAGE_TABLE_LEVEL_4_ADDRESS = 0xffffffff'fffff000; + + /** + * @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained + * in. See https://www.felixcloutier.com/x86/invlpg for more information on the used x86 instruction. + * + * @param address Memory address, which will be used to determine the contained page and flush the TLB entry for + * that page. + */ + auto tlb_flush(paging::virtual_address address) -> void; + + /** + * @brief Invalidates the translation lookaside buffer (TLB) entry for all page tables + */ + auto tlb_flush_all() -> void; + +} // namespace teachos::arch::memory::cpu + +#endif // TEACHOS_ARCH_X86_64_MEMORY_CPU_TLB_HPP diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index 0561420..09fbc76 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -3,7 +3,7 @@ #include "arch/exception_handling/assert.hpp" #include "arch/memory/allocator/concept.hpp" -#include "arch/memory/paging/tlb.hpp" +#include "arch/memory/cpu/tlb.hpp" #include "arch/memory/paging/virtual_page.hpp" #include @@ -165,7 +165,7 @@ namespace teachos::arch::memory::paging } } - tlb_flush(page.start_address()); + cpu::tlb_flush(page.start_address()); } private: diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 23a18dd..9803050 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -1,6 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP +#include "arch/memory/cpu/cr3.hpp" #include "arch/memory/paging/active_page_table.hpp" #include "arch/memory/paging/inactive_page_table.hpp" #include "arch/memory/paging/temporary_page.hpp" @@ -68,21 +69,29 @@ namespace teachos::arch::memory::paging auto remap_elf_kernel_sections(inactive_page_table inactive_table, temporary_page & temporary_page, active_page_table & active_table) -> void { - auto const physical_address = active_table.translate_address(PAGE_TABLE_LEVEL_4_ADDRESS); + auto const physical_address = active_table.translate_address(cpu::PAGE_TABLE_LEVEL_4_ADDRESS); exception_handling::assert(physical_address.has_value(), "[Kernel Mapper] Physical address for active table not mapped"); auto const backup = allocator::physical_frame::containing_address(physical_address.value()); + auto const backup2 = allocator::physical_frame::containing_address(cpu::read_cr3_register()); + cpu::write_cr3_register(0x221000); + auto const backup3 = cpu::read_cr3_register(); + + if (backup == backup2 && backup3 == 0x221000) + { + } + auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); // TODO: Page Table Level 4 is invalid, all entries point to non-existent memory :( active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); - tlb_flush_all(); + cpu::tlb_flush_all(); map_elf_kernel_sections(active_table); page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); - tlb_flush_all(); + cpu::tlb_flush_all(); temporary_page.unmap_page(active_table); } diff --git a/arch/x86_64/include/arch/memory/paging/tlb.hpp b/arch/x86_64/include/arch/memory/paging/tlb.hpp deleted file mode 100644 index 85c4152..0000000 --- a/arch/x86_64/include/arch/memory/paging/tlb.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_TLB_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_TLB_HPP - -#include "arch/memory/paging/virtual_page.hpp" - -namespace teachos::arch::memory::paging -{ - virtual_address constexpr PAGE_TABLE_LEVEL_4_ADDRESS = 0xffffffff'fffff000; - - /** - * @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained - * in. See https://www.felixcloutier.com/x86/invlpg for more information on the used x86 instruction. - * - * @param address Memory address, which will be used to determine the contained page and flush the TLB entry for - * that page. - */ - auto tlb_flush(virtual_address address) -> void; - - /** - * @brief Invalidates the translation lookaside buffer (TLB) entry for all page tables - */ - auto tlb_flush_all() -> void; - -} // namespace teachos::arch::memory::paging - -#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_TLB_HPP -- cgit v1.2.3 From 416f08ee8791aeeb15e216650711f2a84e6f8114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 5 Nov 2024 10:15:25 +0000 Subject: Read cr3 register instead of translating page table level 4 virtual address --- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 9803050..67d1673 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -69,19 +69,7 @@ namespace teachos::arch::memory::paging auto remap_elf_kernel_sections(inactive_page_table inactive_table, temporary_page & temporary_page, active_page_table & active_table) -> void { - auto const physical_address = active_table.translate_address(cpu::PAGE_TABLE_LEVEL_4_ADDRESS); - exception_handling::assert(physical_address.has_value(), - "[Kernel Mapper] Physical address for active table not mapped"); - - auto const backup = allocator::physical_frame::containing_address(physical_address.value()); - auto const backup2 = allocator::physical_frame::containing_address(cpu::read_cr3_register()); - cpu::write_cr3_register(0x221000); - auto const backup3 = cpu::read_cr3_register(); - - if (backup == backup2 && backup3 == 0x221000) - { - } - + auto const backup = allocator::physical_frame::containing_address(cpu::read_cr3_register()); auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); // TODO: Page Table Level 4 is invalid, all entries point to non-existent memory :( -- cgit v1.2.3 From d18cf4a3e4abdea80992b8bba3d1ca50ae215253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 9 Nov 2024 14:51:10 +0000 Subject: Add switch method to kernel --- .../arch/memory/paging/inactive_page_table.hpp | 9 +++++++- .../include/arch/memory/paging/kernel_mapper.hpp | 25 ++++++++++++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp b/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp index 54a53f4..a9ab258 100644 --- a/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp @@ -12,6 +12,13 @@ namespace teachos::arch::memory::paging */ struct inactive_page_table { + /** + * @brief Constructor. + * + * @param frame Frame that should be mapped as the level 4 page table. + */ + inactive_page_table(allocator::physical_frame frame); + /** * @brief Constructor. * @@ -22,7 +29,7 @@ namespace teachos::arch::memory::paging * table. */ inactive_page_table(allocator::physical_frame frame, active_page_table & active_page_table, - temporary_page temporary_page); + temporary_page & temporary_page); allocator::physical_frame page_table_level_4_frame; ///< Temporary level 4 page table }; diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 67d1673..0786ec1 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -44,8 +44,12 @@ namespace teachos::arch::memory::paging auto const frame = allocator.allocate_frame(); exception_handling::assert(frame.has_value(), "[Kernel Mapper] Frame could not be allocated and therefore kernel not mapped"); - inactive_page_table inactive_table{frame.value(), active_table, temporary_page}; - remap_elf_kernel_sections(inactive_table, temporary_page, active_table); + inactive_page_table new_table{frame.value(), active_table, temporary_page}; + remap_elf_kernel_sections(new_table, temporary_page, active_table); + auto const old_table = switch_active_page_table(new_table); + auto const old_level_4_page = + virtual_page::containing_address(old_table.page_table_level_4_frame.start_address()); + active_table.unmap_page(allocator, old_level_4_page); } private: @@ -83,6 +87,23 @@ namespace teachos::arch::memory::paging temporary_page.unmap_page(active_table); } + /** + * @brief Switches the current active table pointed to by the CR3 register with another page table that is currently + * inactive. + * + * @param new_table Inactive page table that should now be made active and replace the current active one. + * @return The previous active page table. + */ + auto switch_active_page_table(inactive_page_table new_table) -> inactive_page_table + { + auto const backup = allocator::physical_frame::containing_address(cpu::read_cr3_register()); + auto const old_table = inactive_page_table{backup}; + + auto const new_address = new_table.page_table_level_4_frame.start_address(); + cpu::write_cr3_register(new_address); + return old_table; + } + /** * @brief Maps the required entries according to every elf section and it's contained frames. Additionally each of * thoose frames gets the correct entry flags according to elf section flags. -- cgit v1.2.3 From 022e2555c233c13f990026ea86d164f56a9cd7be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 9 Nov 2024 15:25:33 +0000 Subject: Remove unused method --- arch/x86_64/include/arch/memory/paging/temporary_page.hpp | 7 ------- 1 file changed, 7 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp index b93a375..a850879 100644 --- a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp @@ -28,13 +28,6 @@ namespace teachos::arch::memory::paging // Nothing to do } - /** - * @brief Set all page table entries to unused. - * - * @param active_table the page table whose values are set to unused. - */ - auto zero_entries(active_page_table & active_table) -> void; - /** * @brief Unmap the current page. * -- cgit v1.2.3 From 4c030cbaee174a9f7f42d4f5ca7ddf6debbbe048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 9 Nov 2024 16:25:11 +0000 Subject: Fix flush all method and move crash. --- arch/x86_64/include/arch/memory/cpu/tlb.hpp | 2 -- arch/x86_64/include/arch/memory/paging/active_page_table.hpp | 6 ++++-- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 2 -- 3 files changed, 4 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/cpu/tlb.hpp b/arch/x86_64/include/arch/memory/cpu/tlb.hpp index dc7ec61..21f09e5 100644 --- a/arch/x86_64/include/arch/memory/cpu/tlb.hpp +++ b/arch/x86_64/include/arch/memory/cpu/tlb.hpp @@ -5,8 +5,6 @@ namespace teachos::arch::memory::cpu { - paging::virtual_address constexpr PAGE_TABLE_LEVEL_4_ADDRESS = 0xffffffff'fffff000; - /** * @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained * in. See https://www.felixcloutier.com/x86/invlpg for more information on the used x86 instruction. diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index 09fbc76..567a806 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -164,8 +164,10 @@ namespace teachos::arch::memory::paging break; } } - - cpu::tlb_flush(page.start_address()); + // TODO: Flushing only specifc page does not work and cause temporary_page.map_table_frame to return an invalid + // page table (Memory inside buffer shows nothing) + // cpu::tlb_flush(page.start_address()); + cpu::tlb_flush_all(); } private: diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 0786ec1..c91c5f0 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -76,8 +76,6 @@ namespace teachos::arch::memory::paging auto const backup = allocator::physical_frame::containing_address(cpu::read_cr3_register()); auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); - // TODO: Page Table Level 4 is invalid, all entries point to non-existent memory :( - active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); cpu::tlb_flush_all(); map_elf_kernel_sections(active_table); -- cgit v1.2.3 From edc11135d83ef1f8fcbc1575a290b31ccbdb7e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 10 Nov 2024 09:34:21 +0000 Subject: Identity map memory map and vga text buffer,w hen setting up kernel --- .../include/arch/memory/paging/kernel_mapper.hpp | 23 +++++++++++++++++++--- .../include/arch/memory/paging/page_entry.hpp | 2 +- arch/x86_64/include/arch/video/vga/text.hpp | 2 ++ 3 files changed, 23 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index c91c5f0..d1b9325 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -5,6 +5,7 @@ #include "arch/memory/paging/active_page_table.hpp" #include "arch/memory/paging/inactive_page_table.hpp" #include "arch/memory/paging/temporary_page.hpp" +#include "arch/video/vga/text.hpp" namespace teachos::arch::memory::paging { @@ -124,19 +125,35 @@ namespace teachos::arch::memory::paging // End address is exclusive, so that it is not part of the section anymore (one past the last frame of this // section). But end frame would now point to the actual last frame and not one past the last frame, therefore // we increment by one to get one past the last frame of this section. - auto end_frame = + auto const end_frame = ++(allocator::physical_frame::containing_address(section.physical_address + section.section_size - 1)); allocator::frame_container::iterator const begin{start_frame}; allocator::frame_container::iterator const end{end_frame}; - allocator::frame_container frames{begin, end}; - entry entry{section.flags}; + allocator::frame_container const frames{begin, end}; + entry const entry{section.flags}; for (auto const & frame : frames) { active_table.identity_map(allocator, frame, entry.get_flags()); } } + + auto const vga_buffer_frame = + allocator::physical_frame::containing_address(video::vga::text::DEFAULT_VGA_TEXT_BUFFER_ADDRESS); + active_table.identity_map(allocator, vga_buffer_frame, entry::WRITABLE); + + auto const multiboot_start_frame = allocator::physical_frame::containing_address(mem_info.multiboot_start); + auto const multiboot_end_frame = ++allocator::physical_frame::containing_address(mem_info.multiboot_end - 1); + + allocator::frame_container::iterator const multiboot_begin{multiboot_start_frame}; + allocator::frame_container::iterator const multiboot_end{multiboot_end_frame}; + allocator::frame_container const multiboot_frames{multiboot_begin, multiboot_end}; + + for (auto const & frame : multiboot_frames) + { + active_table.identity_map(allocator, frame, entry::PRESENT); + } } T & allocator; diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index ab9659d..a7ba262 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -104,7 +104,7 @@ namespace teachos::arch::memory::paging * * @return Extracted entry flags, without the physical address. */ - auto get_flags() -> std::bitset<64U>; + auto get_flags() const -> std::bitset<64U>; private: std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 9 - 11 and 52 - 62 can be diff --git a/arch/x86_64/include/arch/video/vga/text.hpp b/arch/x86_64/include/arch/video/vga/text.hpp index f200da4..665dc1c 100644 --- a/arch/x86_64/include/arch/video/vga/text.hpp +++ b/arch/x86_64/include/arch/video/vga/text.hpp @@ -7,6 +7,8 @@ namespace teachos::arch::video::vga::text { + auto constexpr DEFAULT_VGA_TEXT_BUFFER_ADDRESS = 0xB8000; + /** * @brief The colors available in the standard VGA text mode. */ -- cgit v1.2.3 From 381296c48141e53620281f6f9dfd2aa61723caca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 10 Nov 2024 09:44:42 +0000 Subject: Remove multiboot mapping done in elf section mapping --- arch/x86_64/include/arch/memory/paging/active_page_table.hpp | 4 ++-- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 12 ------------ 2 files changed, 2 insertions(+), 14 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index 567a806..c7d835a 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -166,8 +166,8 @@ namespace teachos::arch::memory::paging } // TODO: Flushing only specifc page does not work and cause temporary_page.map_table_frame to return an invalid // page table (Memory inside buffer shows nothing) - // cpu::tlb_flush(page.start_address()); - cpu::tlb_flush_all(); + cpu::tlb_flush(page.start_address()); + // cpu::tlb_flush_all(); } private: diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index d1b9325..5e51c64 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -142,18 +142,6 @@ namespace teachos::arch::memory::paging auto const vga_buffer_frame = allocator::physical_frame::containing_address(video::vga::text::DEFAULT_VGA_TEXT_BUFFER_ADDRESS); active_table.identity_map(allocator, vga_buffer_frame, entry::WRITABLE); - - auto const multiboot_start_frame = allocator::physical_frame::containing_address(mem_info.multiboot_start); - auto const multiboot_end_frame = ++allocator::physical_frame::containing_address(mem_info.multiboot_end - 1); - - allocator::frame_container::iterator const multiboot_begin{multiboot_start_frame}; - allocator::frame_container::iterator const multiboot_end{multiboot_end_frame}; - allocator::frame_container const multiboot_frames{multiboot_begin, multiboot_end}; - - for (auto const & frame : multiboot_frames) - { - active_table.identity_map(allocator, frame, entry::PRESENT); - } } T & allocator; -- cgit v1.2.3 From 1275612382c5c9d31ed7b24a2c6d699c14a10081 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 10 Nov 2024 10:59:22 +0000 Subject: implement model specific register calls --- arch/x86_64/include/arch/memory/cpu/msr.hpp | 69 +++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 arch/x86_64/include/arch/memory/cpu/msr.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/cpu/msr.hpp b/arch/x86_64/include/arch/memory/cpu/msr.hpp new file mode 100644 index 0000000..662f3ac --- /dev/null +++ b/arch/x86_64/include/arch/memory/cpu/msr.hpp @@ -0,0 +1,69 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_CPU_NXE_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_CPU_NXE_HPP + +#include +#include + +namespace teachos::arch::memory::cpu +{ + constexpr uint32_t IA32_EFER = 0xC0000080; + + enum class msr_flags : uint64_t + { + SCE = 1U << 0ULL, ///< System Call Extensions + LME = 1U << 8ULL, ///< Long Mode Enabled + LMA = 1U << 10ULL, ///< Long Mode Active + NXE = 1U << 11ULL, ///< No-Execute Enable + SVME = 1U << 12ULL, ///< Secure Virtual Machine Enable + LMSLE = 1U << 13ULL, ///< Secure Virtual Machine Enable + FFXSR = 1U << 14ULL, ///< fast FXSAVE/FXSTOR + TCE = 1U << 15ULL, ///< Translation Cache Extension + }; + + /** + * @brief Reads a 64-bit Model-Specific Register (MSR). + * + * This function reads the value of an MSR specified by the given address. It + * combines the lower and upper 32-bits of the MSR value and returns it as a + * 64-bit unsigned integer. + * + * @param msr The address of the MSR to read. + * @return The 64-bit value read from the MSR. + */ + uint64_t read_msr(uint32_t msr); + + /** + * @brief Writes a 64-bit value to a Model-Specific Register (MSR). + * + * This function writes a 64-bit value to the MSR specified by the given address. + * It splits the 64-bit value into two 32-bit parts and writes them using the + * `wrmsr` instruction. + * + * @param msr The address of the MSR to write to. + * @param value The 64-bit value to write to the MSR. + */ + void write_msr(uint32_t msr, uint64_t value); + + /** + * @brief Sets a specific bit in the MSR register. + * + * This function reads the current value of the EFER register, ORs the specified + * bit with the current value, and writes the updated value back to the EFER register. + * + * @param flag The flag to set in the EFER register. + */ + void set_msr_bit(msr_flags flag); + + /** + * @brief Enables the No-Execute Enable (NXE) bit in the Extended Feature Enable Register (EFER). + * + * This function reads the current value of the EFER register, enables the NXE bit + * (bit 11), and writes the updated value back to the EFER register. Enabling the NXE + * bit allows the processor to support No-Execute memory regions, which are required + * for certain memory protection features like Data Execution Prevention (DEP). + */ + void enable_nxe_bit(); + +} // namespace teachos::arch::memory::cpu + +#endif // TEACHOS_ARCH_X86_64_MEMORY_CPU_NXE_HPP \ No newline at end of file -- cgit v1.2.3 From 45e7b24f19b3c4557f98996a44d8857d750ca5b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 10 Nov 2024 11:45:26 +0000 Subject: Adjust comments and constant --- .../include/arch/memory/cpu/control_register.hpp | 70 ++++++++++++++++++++++ arch/x86_64/include/arch/memory/cpu/cr3.hpp | 27 --------- arch/x86_64/include/arch/memory/cpu/msr.hpp | 47 ++++++++------- .../include/arch/memory/paging/kernel_mapper.hpp | 10 ++-- 4 files changed, 102 insertions(+), 52 deletions(-) create mode 100644 arch/x86_64/include/arch/memory/cpu/control_register.hpp delete mode 100644 arch/x86_64/include/arch/memory/cpu/cr3.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/cpu/control_register.hpp b/arch/x86_64/include/arch/memory/cpu/control_register.hpp new file mode 100644 index 0000000..b48e48c --- /dev/null +++ b/arch/x86_64/include/arch/memory/cpu/control_register.hpp @@ -0,0 +1,70 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP + +#include + +namespace teachos::arch::memory::cpu +{ + /** + * @brief Control registers that can be read and written to. + * + * @note CR1 and CR5 - 7 are reserved and will throw an exception if they are accessed, therefore they are not defined + * in the enum. See https://en.wikipedia.org/wiki/Control_register#Control_registers_in_Intel_x86_series for more + * information. + */ + enum struct control_register : uint8_t + { + CR0, ///< Contains various control flags that modify basic operation of the processor, Machine Status World (MSW) + ///< register. + CR2 = 2U, ///< Contains Page Fault Linear Address (PFLA), when page fault occurs address program attended to accces + ///< is stored here. + CR3, ///< Enables process to translate linear addresses into physical addresses using paging, CR0 bit 32 Paging + ///< (PG) needs to be enabled simply contains the register value that represents the physical address of the + ///< level 4 page table used for paging in the system. Therefore reading this value allows to access the level + ///< 4 page table directly. Instead of over the virtual address 0xffffffff'fffff000, which then has to be + ///< first translated into a physical address. + CR4 ///< Used in protected mode to control operations. + }; + + /** + * @brief Control register 2 flags that can be set. + * + * @note Modifies the basic operation of the processor. Only the most important extensions are listed below, the rest + * are excluded for brevity. See https://en.wikipedia.org/wiki/Control_register#CR0 for more information. + */ + enum struct cr2_flags : uint32_t + { + PROTECTED_MODE_ENABLED = 1U << 0U, ///< System is in protected moe else system is in real mode. + TASK_SWITCHED = 1U << 3U, ///< Allows saving x87 task context upon a task switch only after x87 instruction used. + WRITE_PROTECT = 1U << 16U, ///< When set, the CPU cannot write to read-only pages when privilege level is 0. + PAGING = 1U << 31U, // Enable paging using the CR3 register. + }; + + /** + * @brief Reads the value of the given control register. + * + * @note The cr3 register value represents the physical address of the level 4 page table used for paging in the + * system. Therefore reading this value allows to access the level 4 page table directly. Instead of over the virtual + * address 0xffffffff'fffff000, which then has to be first translated into a physical address. + * + * @return Physical address the level 4 page table is located at. + */ + + /** + * @brief Reads the value of the given control register. + * + * @param cr Control register that should be read. + * @return Value of the control register. + */ + auto read_control_register(control_register cr) -> std::size_t; + + /** + * @brief Writes the given value into the given control register. + * + * @param cr Control register that should be written. + * @param new_value New value that should be written. + */ + auto write_control_register(control_register cr, std::size_t new_value) -> void; +} // namespace teachos::arch::memory::cpu + +#endif // TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP diff --git a/arch/x86_64/include/arch/memory/cpu/cr3.hpp b/arch/x86_64/include/arch/memory/cpu/cr3.hpp deleted file mode 100644 index 51d5055..0000000 --- a/arch/x86_64/include/arch/memory/cpu/cr3.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP - -#include "arch/memory/allocator/physical_frame.hpp" - -namespace teachos::arch::memory::cpu -{ - /** - * @brief Reads the value of the cr3 register. - * - * @note The cr3 register value represents the physical address of the level 4 page table used for paging in the - * system. Therefore reading this value allows to access the level 4 page table directly. Instead of over the virtual - * address 0xffffffff'fffff000, which then has to be first translated into a physical address. - * - * @return Physical address the level 4 page table is located at. - */ - auto read_cr3_register() -> allocator::physical_address; - - /** - * @brief Writes the given value into the cr3 register. - * - * @param new_p4_table_address Physical address the newly kernel mapped level 4 page table is located at. - */ - auto write_cr3_register(allocator::physical_address new_p4_table_address) -> void; -} // namespace teachos::arch::memory::cpu - -#endif // TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP diff --git a/arch/x86_64/include/arch/memory/cpu/msr.hpp b/arch/x86_64/include/arch/memory/cpu/msr.hpp index 662f3ac..1403995 100644 --- a/arch/x86_64/include/arch/memory/cpu/msr.hpp +++ b/arch/x86_64/include/arch/memory/cpu/msr.hpp @@ -6,63 +6,68 @@ namespace teachos::arch::memory::cpu { - constexpr uint32_t IA32_EFER = 0xC0000080; - - enum class msr_flags : uint64_t + /** + * @brief Important Flags that can be writen into the Extended Feature Enable Register (EFER). + * + * @note EFER is a model-specific register allowing to configure CPU extensions. Only the most important extensions + * are listed below, the rest are excluded for brevity. See https://en.wikipedia.org/wiki/Control_register#EFER for + * more information. + */ + enum class efer_flags : uint64_t { - SCE = 1U << 0ULL, ///< System Call Extensions - LME = 1U << 8ULL, ///< Long Mode Enabled - LMA = 1U << 10ULL, ///< Long Mode Active - NXE = 1U << 11ULL, ///< No-Execute Enable - SVME = 1U << 12ULL, ///< Secure Virtual Machine Enable - LMSLE = 1U << 13ULL, ///< Secure Virtual Machine Enable - FFXSR = 1U << 14ULL, ///< fast FXSAVE/FXSTOR - TCE = 1U << 15ULL, ///< Translation Cache Extension + SCE = 1UL << 0UL, ///< System Call Extensions + LME = 1UL << 8UL, ///< Long Mode Enabled + LMA = 1UL << 10UL, ///< Long Mode Active + NXE = 1UL << 11UL, ///< No-Execute Enable + SVME = 1UL << 12UL, ///< Secure Virtual Machine Enable + LMSLE = 1UL << 13UL, ///< Long Mode Segment Limit Enable + FFXSR = 1UL << 14UL, ///< Fast FXSAVE/FXSTOR + TCE = 1UL << 15UL, ///< Translation Cache Extension }; /** * @brief Reads a 64-bit Model-Specific Register (MSR). * - * This function reads the value of an MSR specified by the given address. It + * @note This function reads the value of an MSR specified by the given address. It * combines the lower and upper 32-bits of the MSR value and returns it as a * 64-bit unsigned integer. * * @param msr The address of the MSR to read. * @return The 64-bit value read from the MSR. */ - uint64_t read_msr(uint32_t msr); + auto read_msr(uint32_t msr) -> void; /** * @brief Writes a 64-bit value to a Model-Specific Register (MSR). * - * This function writes a 64-bit value to the MSR specified by the given address. + * @note This function writes a 64-bit value to the MSR specified by the given address. * It splits the 64-bit value into two 32-bit parts and writes them using the * `wrmsr` instruction. * * @param msr The address of the MSR to write to. - * @param value The 64-bit value to write to the MSR. + * @param new_value The 64-bit value to write to the MSR. */ - void write_msr(uint32_t msr, uint64_t value); + auto write_msr(uint32_t msr, uint64_t new_value) -> void; /** - * @brief Sets a specific bit in the MSR register. + * @brief Sets a specific bit in the Extended Feature Enable Register (EFER) Model-Specific Register (MSR) register. * - * This function reads the current value of the EFER register, ORs the specified + * @note This function reads the current value of the EFER register, ORs the specified * bit with the current value, and writes the updated value back to the EFER register. * * @param flag The flag to set in the EFER register. */ - void set_msr_bit(msr_flags flag); + auto set_efer_bit(efer_flags flag) -> void; /** * @brief Enables the No-Execute Enable (NXE) bit in the Extended Feature Enable Register (EFER). * - * This function reads the current value of the EFER register, enables the NXE bit + * @note This function reads the current value of the EFER register, enables the NXE bit * (bit 11), and writes the updated value back to the EFER register. Enabling the NXE * bit allows the processor to support No-Execute memory regions, which are required * for certain memory protection features like Data Execution Prevention (DEP). */ - void enable_nxe_bit(); + auto enable_nxe_bit() -> void; } // namespace teachos::arch::memory::cpu diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 5e51c64..53284b6 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -1,7 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP -#include "arch/memory/cpu/cr3.hpp" +#include "arch/memory/cpu/control_register.hpp" #include "arch/memory/paging/active_page_table.hpp" #include "arch/memory/paging/inactive_page_table.hpp" #include "arch/memory/paging/temporary_page.hpp" @@ -74,7 +74,8 @@ namespace teachos::arch::memory::paging auto remap_elf_kernel_sections(inactive_page_table inactive_table, temporary_page & temporary_page, active_page_table & active_table) -> void { - auto const backup = allocator::physical_frame::containing_address(cpu::read_cr3_register()); + auto const backup = + allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3)); auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); @@ -95,11 +96,12 @@ namespace teachos::arch::memory::paging */ auto switch_active_page_table(inactive_page_table new_table) -> inactive_page_table { - auto const backup = allocator::physical_frame::containing_address(cpu::read_cr3_register()); + auto const backup = + allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3)); auto const old_table = inactive_page_table{backup}; auto const new_address = new_table.page_table_level_4_frame.start_address(); - cpu::write_cr3_register(new_address); + cpu::write_control_register(cpu::control_register::CR3, new_address); return old_table; } -- cgit v1.2.3 From 8eb68ccb8837ba867550d16f967d9ef21921abe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 10 Nov 2024 12:08:02 +0000 Subject: Finish control register and adjust msr --- .../include/arch/memory/cpu/control_register.hpp | 28 +++++++++++----------- arch/x86_64/include/arch/memory/cpu/msr.hpp | 13 +--------- 2 files changed, 15 insertions(+), 26 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/cpu/control_register.hpp b/arch/x86_64/include/arch/memory/cpu/control_register.hpp index b48e48c..4988036 100644 --- a/arch/x86_64/include/arch/memory/cpu/control_register.hpp +++ b/arch/x86_64/include/arch/memory/cpu/control_register.hpp @@ -32,7 +32,7 @@ namespace teachos::arch::memory::cpu * @note Modifies the basic operation of the processor. Only the most important extensions are listed below, the rest * are excluded for brevity. See https://en.wikipedia.org/wiki/Control_register#CR0 for more information. */ - enum struct cr2_flags : uint32_t + enum struct cr2_flags : uint64_t { PROTECTED_MODE_ENABLED = 1U << 0U, ///< System is in protected moe else system is in real mode. TASK_SWITCHED = 1U << 3U, ///< Allows saving x87 task context upon a task switch only after x87 instruction used. @@ -40,31 +40,31 @@ namespace teachos::arch::memory::cpu PAGING = 1U << 31U, // Enable paging using the CR3 register. }; - /** - * @brief Reads the value of the given control register. - * - * @note The cr3 register value represents the physical address of the level 4 page table used for paging in the - * system. Therefore reading this value allows to access the level 4 page table directly. Instead of over the virtual - * address 0xffffffff'fffff000, which then has to be first translated into a physical address. - * - * @return Physical address the level 4 page table is located at. - */ - /** * @brief Reads the value of the given control register. * * @param cr Control register that should be read. * @return Value of the control register. */ - auto read_control_register(control_register cr) -> std::size_t; + auto read_control_register(control_register cr) -> uint64_t; /** - * @brief Writes the given value into the given control register. + * @brief Sets a specific bit in the Extended Feature Enable Register (EFER) Model-Specific Register (MSR) register. * * @param cr Control register that should be written. * @param new_value New value that should be written. */ - auto write_control_register(control_register cr, std::size_t new_value) -> void; + auto write_control_register(control_register cr, uint64_t new_value) -> void; + + /** + * @brief Sets a specific bit in the CR2. + * + * @note This function reads the current value of the CR2 register, ORs the specified + * bit with the current value, and writes the updated value back to the CR2. + * + * @param flag he flag to set in the CR2. + */ + auto set_cr2_bit(cr2_flags flag) -> void; } // namespace teachos::arch::memory::cpu #endif // TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP diff --git a/arch/x86_64/include/arch/memory/cpu/msr.hpp b/arch/x86_64/include/arch/memory/cpu/msr.hpp index 1403995..49e9bcf 100644 --- a/arch/x86_64/include/arch/memory/cpu/msr.hpp +++ b/arch/x86_64/include/arch/memory/cpu/msr.hpp @@ -35,7 +35,7 @@ namespace teachos::arch::memory::cpu * @param msr The address of the MSR to read. * @return The 64-bit value read from the MSR. */ - auto read_msr(uint32_t msr) -> void; + auto read_msr(uint32_t msr) -> uint64_t; /** * @brief Writes a 64-bit value to a Model-Specific Register (MSR). @@ -58,17 +58,6 @@ namespace teachos::arch::memory::cpu * @param flag The flag to set in the EFER register. */ auto set_efer_bit(efer_flags flag) -> void; - - /** - * @brief Enables the No-Execute Enable (NXE) bit in the Extended Feature Enable Register (EFER). - * - * @note This function reads the current value of the EFER register, enables the NXE bit - * (bit 11), and writes the updated value back to the EFER register. Enabling the NXE - * bit allows the processor to support No-Execute memory regions, which are required - * for certain memory protection features like Data Execution Prevention (DEP). - */ - auto enable_nxe_bit() -> void; - } // namespace teachos::arch::memory::cpu #endif // TEACHOS_ARCH_X86_64_MEMORY_CPU_NXE_HPP \ No newline at end of file -- cgit v1.2.3 From 0f3c5c2bc02d7aa48f8edbe42a67dd91821032b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 11 Nov 2024 12:02:35 +0000 Subject: Mark the two methods that first work and then fail --- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 53284b6..10fad0c 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -76,6 +76,7 @@ namespace teachos::arch::memory::paging { auto const backup = allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3)); + // TODO: This creates invalid page table that points to nothing, is it the frame (current level 4 page table) auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); -- cgit v1.2.3 From 0ca0c40c197c214288ad2ed1179ae9ae28c50194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 11 Nov 2024 14:16:18 +0000 Subject: Improve calculation of kernel end and start address. --- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 10fad0c..f01bd37 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -38,7 +38,7 @@ namespace teachos::arch::memory::paging * inactive page table, that is not used by the CPU to ensure we are not changign memory that we are using. Because * remapping active kernel memory in the kernel wouldn't work. */ - auto remap_kernel() -> void + auto remap_kernel() -> active_page_table & { temporary_page temporary_page{virtual_page{0xCAFEBABE}, allocator}; auto & active_table = active_page_table::create_or_get(); @@ -51,6 +51,7 @@ namespace teachos::arch::memory::paging auto const old_level_4_page = virtual_page::containing_address(old_table.page_table_level_4_frame.start_address()); active_table.unmap_page(allocator, old_level_4_page); + return active_table; } private: -- cgit v1.2.3 From f45fdae9913a9d8e003cf681621e71516b2054b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 12 Nov 2024 08:50:05 +0000 Subject: Add notes on why system crashes --- arch/x86_64/include/arch/memory/paging/active_page_table.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index c7d835a..c5b972b 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -166,8 +166,11 @@ namespace teachos::arch::memory::paging } // TODO: Flushing only specifc page does not work and cause temporary_page.map_table_frame to return an invalid // page table (Memory inside buffer shows nothing) - cpu::tlb_flush(page.start_address()); - // cpu::tlb_flush_all(); + // cpu::tlb_flush(page.start_address()); + // This is the case, because we have unmapped the active page and it is completly invalid, if we only flush one + // page, the other pages which are huge still exist in the cache and can therefore still be accessed. But because + // they are huge pages the temporary page is not mapped correctly. + cpu::tlb_flush_all(); } private: -- cgit v1.2.3 From 13887617b17d9387e218ce702087b6a7140af9bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 12 Nov 2024 09:26:12 +0000 Subject: Remap kernel inplace. --- .../include/arch/memory/paging/kernel_mapper.hpp | 23 +++++++++++----------- 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index f01bd37..f673da4 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -40,17 +40,17 @@ namespace teachos::arch::memory::paging */ auto remap_kernel() -> active_page_table & { - temporary_page temporary_page{virtual_page{0xCAFEBABE}, allocator}; + /*temporary_page temporary_page{virtual_page{0xCAFEBABE}, allocator};*/ auto & active_table = active_page_table::create_or_get(); - auto const frame = allocator.allocate_frame(); + /*auto const frame = allocator.allocate_frame(); exception_handling::assert(frame.has_value(), "[Kernel Mapper] Frame could not be allocated and therefore kernel not mapped"); - inactive_page_table new_table{frame.value(), active_table, temporary_page}; - remap_elf_kernel_sections(new_table, temporary_page, active_table); - auto const old_table = switch_active_page_table(new_table); + inactive_page_table new_table{frame.value(), active_table, temporary_page};*/ + remap_elf_kernel_sections(active_table); + /*auto const old_table = switch_active_page_table(new_table); auto const old_level_4_page = virtual_page::containing_address(old_table.page_table_level_4_frame.start_address()); - active_table.unmap_page(allocator, old_level_4_page); + active_table.unmap_page(allocator, old_level_4_page);*/ return active_table; } @@ -72,21 +72,20 @@ namespace teachos::arch::memory::paging * @param active_table Active level 4 page table that has its recursive mapping overwritten temporarily and then * restored once the process is finished. */ - auto remap_elf_kernel_sections(inactive_page_table inactive_table, temporary_page & temporary_page, - active_page_table & active_table) -> void + auto remap_elf_kernel_sections(active_page_table & active_table) -> void { - auto const backup = + /*auto const backup = allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3)); // TODO: This creates invalid page table that points to nothing, is it the frame (current level 4 page table) auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); - active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); + active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE);*/ cpu::tlb_flush_all(); map_elf_kernel_sections(active_table); - page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); + /*page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE);*/ cpu::tlb_flush_all(); - temporary_page.unmap_page(active_table); + /*temporary_page.unmap_page(active_table);*/ } /** -- cgit v1.2.3 From 7db57d7a47671b4023e34413a2276611e1c65f72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 12 Nov 2024 10:24:12 +0000 Subject: Add comment to flush all and remove now redudant todos. --- arch/x86_64/include/arch/memory/paging/active_page_table.hpp | 9 +++------ arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 1 - 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index c5b972b..1bc5b74 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -164,12 +164,9 @@ namespace teachos::arch::memory::paging break; } } - // TODO: Flushing only specifc page does not work and cause temporary_page.map_table_frame to return an invalid - // page table (Memory inside buffer shows nothing) - // cpu::tlb_flush(page.start_address()); - // This is the case, because we have unmapped the active page and it is completly invalid, if we only flush one - // page, the other pages which are huge still exist in the cache and can therefore still be accessed. But because - // they are huge pages the temporary page is not mapped correctly. + // Uses flush all instead of cpu::tlb_flush(page.start_address());, because when we unmap the active page and + // only flush one page, the rest of the page which is huge still exist in the cache and + // can therefore still be accessed. But because they are huge pages the new mapping can not be accessed correctly. cpu::tlb_flush_all(); } diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index f673da4..bcc3eba 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -76,7 +76,6 @@ namespace teachos::arch::memory::paging { /*auto const backup = allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3)); - // TODO: This creates invalid page table that points to nothing, is it the frame (current level 4 page table) auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE);*/ -- cgit v1.2.3 From 9507633f04e672b3dadf1385b1562fb3101d0ea3 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 12 Nov 2024 10:41:23 +0000 Subject: add debug statements --- arch/x86_64/include/arch/memory/paging/active_page_table.hpp | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index c5b972b..9931711 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -214,6 +214,7 @@ namespace teachos::arch::memory::paging allocator.deallocate_frame(frame.value()); } + public: page_table_handle active_handle; ///< Underlying active level 4 page table }; -- cgit v1.2.3 From d10bc808b29b0b647cbbb6c92d253fbb8c5cf431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 12 Nov 2024 10:59:50 +0000 Subject: Fix next table overwriting old page handle --- arch/x86_64/include/arch/memory/paging/page_table.hpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 9449ef2..7a15875 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -72,7 +72,7 @@ namespace teachos::arch::memory::paging * * @param table_index Index of this page table in the page table one level lower. */ - auto next_table(std::size_t table_index) -> std::optional; + auto next_table(std::size_t table_index) const -> std::optional; /** * @brief Call next_table and then checks if the table already exists, if it does not it will use the given @@ -120,8 +120,8 @@ namespace teachos::arch::memory::paging auto operator[](std::size_t index) const -> entry const &; /** - * @brief Decrements the page table level enum by one, is defined so we can use it as a replacement for an - * int index in a range based for loop. + * @brief Pre decrement operator on the page table level enum, is defined so we can use it as a replacement + * for an int index in a range based for loop. * * @note Will halt execution if called with page_table_handle::LEVEL1, because there is no level below. Has to be * defined as either a friend function or inline header method, because we define an operator of another type. In @@ -132,12 +132,13 @@ namespace teachos::arch::memory::paging * header file. * * @param value Value we want to decrement on - * @return level New level value decrement by one, meaning the level is also decrement by one Level4 --> Level3, ... + * @return New level value decrement by one, meaning the level is also decrement by one Level4 --> Level3, ... */ friend auto operator--(level & value) -> level &; private: - page_table * table; ///< Handle to underlying page table, can never be null (invariant ensured by constructor) + page_table * table; ///< Handle to underlying page table, can never be null (invariant ensured by + ///< constructor) level table_level; ///< Level page table is currently on, depends on how often next_level was ///< called successfully. }; -- cgit v1.2.3 From fde3f969c5c45d4cdbd5ec92c4d07fd157194300 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 19 Nov 2024 09:38:44 +0100 Subject: memory: fix kernel remapping --- .../arch/memory/paging/active_page_table.hpp | 23 ++-------------------- .../include/arch/memory/paging/kernel_mapper.hpp | 23 +++++++++++----------- 2 files changed, 14 insertions(+), 32 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index a60b3ad..8b12800 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -136,7 +136,6 @@ namespace teachos::arch::memory::paging "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); auto current_handle = active_handle; - std::array handles{current_handle, current_handle, current_handle}; for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) { @@ -146,28 +145,10 @@ namespace teachos::arch::memory::paging // fail. This can only mean that we attempted to unmap a huge page, which is not supported in the first place. exception_handling::assert(next_handle.has_value(), "[Page Mapper] Unable to unmap huge pages"); current_handle = next_handle.value(); - // The level is used as the index, because it ensures the first level is the lowest one and then the remaining - // levels in ascending order. This is required, because we first have to clear the Level 1 page entry to check - // if the Level 1 page is now empty, to clear the Level 2 page entry, which will then also check if the Level 2 - // page is empty and clear the Level 3 page entry and so on. - handles.at(level - 1U) = current_handle; } - // Unmaps all entries starting from the Level 1 page table, and unmaps higher levels as well if that entry was the - // last one. We check if it was the last one using is empty on the page table handle, when we have removed the - // page to be unmapped. - for (auto & handle : handles) - { - unmap_page_table_entry(allocator, page, handle); - if (!handle.is_empty()) - { - break; - } - } - // Uses flush all instead of cpu::tlb_flush(page.start_address());, because when we unmap the active page and - // only flush one page, the rest of the page which is huge still exist in the cache and - // can therefore still be accessed. But because they are huge pages the new mapping can not be accessed correctly. - cpu::tlb_flush_all(); + unmap_page_table_entry(allocator, page, current_handle); + cpu::tlb_flush(page.start_address()); } private: diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index bcc3eba..f980451 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -40,17 +40,17 @@ namespace teachos::arch::memory::paging */ auto remap_kernel() -> active_page_table & { - /*temporary_page temporary_page{virtual_page{0xCAFEBABE}, allocator};*/ + temporary_page temporary_page{virtual_page{0xCAFEBABE}, allocator}; auto & active_table = active_page_table::create_or_get(); - /*auto const frame = allocator.allocate_frame(); + auto const frame = allocator.allocate_frame(); exception_handling::assert(frame.has_value(), "[Kernel Mapper] Frame could not be allocated and therefore kernel not mapped"); - inactive_page_table new_table{frame.value(), active_table, temporary_page};*/ - remap_elf_kernel_sections(active_table); - /*auto const old_table = switch_active_page_table(new_table); + inactive_page_table new_table{frame.value(), active_table, temporary_page}; + remap_elf_kernel_sections(new_table, temporary_page, active_table); + auto const old_table = switch_active_page_table(new_table); auto const old_level_4_page = virtual_page::containing_address(old_table.page_table_level_4_frame.start_address()); - active_table.unmap_page(allocator, old_level_4_page);*/ + active_table.unmap_page(allocator, old_level_4_page); return active_table; } @@ -72,19 +72,20 @@ namespace teachos::arch::memory::paging * @param active_table Active level 4 page table that has its recursive mapping overwritten temporarily and then * restored once the process is finished. */ - auto remap_elf_kernel_sections(active_page_table & active_table) -> void + auto remap_elf_kernel_sections(inactive_page_table & inactive_table, temporary_page & temporary_page, + active_page_table & active_table) -> void { - /*auto const backup = + auto const backup = allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3)); auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); - active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE);*/ + active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); cpu::tlb_flush_all(); map_elf_kernel_sections(active_table); - /*page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE);*/ + page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); cpu::tlb_flush_all(); - /*temporary_page.unmap_page(active_table);*/ + temporary_page.unmap_page(active_table); } /** -- cgit v1.2.3 From 1cd666241b59b800818812220e28b8b8572e4263 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 19 Nov 2024 17:32:02 +0100 Subject: paging: de-templetize implementation --- .../arch/memory/allocator/area_frame_allocator.hpp | 7 +- .../include/arch/memory/allocator/concept.hpp | 22 ----- .../arch/memory/allocator/frame_allocator.hpp | 19 +++++ .../arch/memory/allocator/tiny_frame_allocator.hpp | 11 ++- .../arch/memory/paging/active_page_table.hpp | 83 +++---------------- .../include/arch/memory/paging/kernel_mapper.hpp | 94 +++------------------- .../include/arch/memory/paging/page_table.hpp | 23 +----- .../include/arch/memory/paging/temporary_page.hpp | 8 +- 8 files changed, 54 insertions(+), 213 deletions(-) delete mode 100644 arch/x86_64/include/arch/memory/allocator/concept.hpp create mode 100644 arch/x86_64/include/arch/memory/allocator/frame_allocator.hpp (limited to 'arch/x86_64/include') 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 f2b77f8..f1a3a64 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,6 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP #define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP +#include "arch/memory/allocator/frame_allocator.hpp" #include "arch/memory/allocator/physical_frame.hpp" #include "arch/memory/multiboot/reader.hpp" @@ -11,7 +12,7 @@ namespace teachos::arch::memory::allocator /** * @brief Allocates memory using memory areas read from the multiboot2 information pointer. */ - struct area_frame_allocator + struct area_frame_allocator : frame_allocator { /** * @brief Constructor @@ -32,7 +33,7 @@ namespace teachos::arch::memory::allocator * * @return next free physical frame or nullopt if none was found. */ - auto allocate_frame() -> std::optional; + auto allocate_frame() -> std::optional override; /** * @brief Deallocates a previously allocated physical frame. @@ -43,7 +44,7 @@ namespace teachos::arch::memory::allocator * * @param physical_frame Previously allocated physical_frame that should be deallocated. */ - auto deallocate_frame(physical_frame physical_frame) -> void; + auto deallocate_frame(physical_frame const & physical_frame) -> void override; private: /** diff --git a/arch/x86_64/include/arch/memory/allocator/concept.hpp b/arch/x86_64/include/arch/memory/allocator/concept.hpp deleted file mode 100644 index 4a7ab72..0000000 --- a/arch/x86_64/include/arch/memory/allocator/concept.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_CONCEPT_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_CONCEPT_HPP - -#include "arch/memory/allocator/physical_frame.hpp" - -#include - -namespace teachos::arch::memory::allocator -{ - /** - * @brief Frame allocator concept - * - * @tparam T - */ - template - concept FrameAllocator = requires(T t, physical_frame a) { - { t.allocate_frame() } -> std::same_as>; - { t.deallocate_frame(a) } -> std::same_as; - }; -} // namespace teachos::arch::memory::allocator - -#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_CONCEPT_HPP diff --git a/arch/x86_64/include/arch/memory/allocator/frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/frame_allocator.hpp new file mode 100644 index 0000000..9316ca9 --- /dev/null +++ b/arch/x86_64/include/arch/memory/allocator/frame_allocator.hpp @@ -0,0 +1,19 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_FRAME_ALLOCATOR_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_FRAME_ALLOCATOR_HPP + +#include "arch/memory/allocator/physical_frame.hpp" + +#include + +namespace teachos::arch::memory::allocator +{ + + struct frame_allocator + { + auto virtual allocate_frame() -> std::optional = 0; + auto virtual deallocate_frame(physical_frame const & frame) -> void = 0; + }; // namespace teachos::arch::memory::allocator + +} // namespace teachos::arch::memory::allocator + +#endif \ No newline at end of file diff --git a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp index a96b743..c449ac8 100644 --- a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp @@ -1,8 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP #define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP -#include "arch/memory/allocator/area_frame_allocator.hpp" -#include "arch/memory/allocator/concept.hpp" +#include "arch/memory/allocator/frame_allocator.hpp" #include "arch/memory/allocator/physical_frame.hpp" #include @@ -17,7 +16,7 @@ namespace teachos::arch::memory::allocator /** * @brief Allocates memory using memory areas read from the multiboot2 information pointer. */ - struct tiny_frame_allocator + struct tiny_frame_allocator : frame_allocator { /** * @brief Constructor. @@ -27,7 +26,7 @@ namespace teachos::arch::memory::allocator * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate * entries *when a new page table is required. */ - tiny_frame_allocator(area_frame_allocator & allocator); + tiny_frame_allocator(frame_allocator & allocator); /** * @brief Allocate memory by finding and returning one of the three free physical frames. @@ -35,7 +34,7 @@ namespace teachos::arch::memory::allocator * @return First free physical frames of the three frames held by this allocator or nullopt if we used up all three * frames already. */ - auto allocate_frame() -> std::optional; + auto allocate_frame() -> std::optional override; /** * @brief Deallocates one of the three previously allocated physical frames. @@ -45,7 +44,7 @@ namespace teachos::arch::memory::allocator * * @param physical_frame Previously allocated physical_frame that should be deallocated. */ - auto deallocate_frame(physical_frame physical_frame) -> void; + auto deallocate_frame(physical_frame const & physical_frame) -> void override; private: std::array, TINY_ALLOCATOR_FRAMES_COUNT> frames = diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index 8b12800..e558fa5 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -1,12 +1,13 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_ACTIVE_PAGE_TABLE_HPP #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_ACTIVE_PAGE_TABLE_HPP -#include "arch/exception_handling/assert.hpp" -#include "arch/memory/allocator/concept.hpp" -#include "arch/memory/cpu/tlb.hpp" +#include "arch/memory/allocator/frame_allocator.hpp" +#include "arch/memory/allocator/physical_frame.hpp" +#include "arch/memory/paging/page_table.hpp" #include "arch/memory/paging/virtual_page.hpp" #include +#include #include namespace teachos::arch::memory::paging @@ -65,44 +66,21 @@ namespace teachos::arch::memory::paging * @note Allocates and maps an entry in every page level if it does not exists yet down to level 1. If the level 1 * page table already exists it halts execution instead. * - * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and - * deallocate method. * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate * entries when a new page table is required. * @param page Virtual page that is being mapped. * @param frame Physical frame that the virtual page will be mapped to. * @param flags A bitset of flags that configure the page table entry for this mapping. */ - template - auto map_page_to_frame(T & allocator, virtual_page page, allocator::physical_frame frame, - std::bitset<64U> flags) -> void - { - auto current_handle = active_handle; - - for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) - { - current_handle = current_handle.next_table_or_create(allocator, page.get_level_index(level)); - } - - auto & level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; - arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE), - "[Page Mapper] Unable to map huge pages"); - arch::exception_handling::assert(level1_entry.is_unused(), "[Page Mapper] Page table entry is already used"); - level1_entry.set_entry(frame, flags.to_ulong() | entry::PRESENT); - } - + auto map_page_to_frame(allocator::frame_allocator & allocator, virtual_page page, allocator::physical_frame frame, + std::bitset<64U> flags) -> void; /** * @brief Allocates the next free frame and then uses that frame to call map_page_to_frame. * * @see map_page_to_frame */ - template - auto map_next_free_page_to_frame(T & allocator, virtual_page page, std::bitset<64U> flags) -> void - { - auto const frame = allocator.allocate_frame(); - exception_handling::assert(frame.has_value(), "[Page mapper] Out of memory exception"); - map_page_to_frame(allocator, page, frame.value(), flags); - } + auto map_next_free_page_to_frame(allocator::frame_allocator & allocator, virtual_page page, + std::bitset<64U> flags) -> void; /** * @brief Gets the corresponding page the given frame has to be contained in and uses that to call @@ -110,12 +88,8 @@ namespace teachos::arch::memory::paging * * @see map_page_to_frame */ - template - auto identity_map(T & allocator, allocator::physical_frame frame, std::bitset<64U> flags) -> void - { - auto const page = virtual_page::containing_address(frame.start_address()); - map_page_to_frame(allocator, page, frame, flags); - } + auto identity_map(allocator::frame_allocator & allocator, allocator::physical_frame frame, + std::bitset<64U> flags) -> void; /** * @brief Unmaps the virtual page from the previously mapped to physical frame and resets the flags. @@ -129,27 +103,7 @@ namespace teachos::arch::memory::paging * entries when a new page table is required. * @param page Virtual page that is being unmapped. */ - template - auto unmap_page(T & allocator, virtual_page page) -> void - { - exception_handling::assert(translate_page(page).has_value(), - "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); - - auto current_handle = active_handle; - - for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) - { - auto const level_index = page.get_level_index(level); - auto const next_handle = current_handle.next_table(level_index); - // The next table method failed even tough the page has to be mapped already, because translate_page did not - // fail. This can only mean that we attempted to unmap a huge page, which is not supported in the first place. - exception_handling::assert(next_handle.has_value(), "[Page Mapper] Unable to unmap huge pages"); - current_handle = next_handle.value(); - } - - unmap_page_table_entry(allocator, page, current_handle); - cpu::tlb_flush(page.start_address()); - } + auto unmap_page(allocator::frame_allocator & allocator, virtual_page page) -> void; private: /** @@ -173,24 +127,13 @@ namespace teachos::arch::memory::paging /** * @brief Unmaps specific page at the current internal handle level. * - * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and - * deallocate method. * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate * entries *when a new page table is required. * @param page Virtual page that is being unmapped. * @param handle Page Table handle we want to access the entry that should be cleared on. */ - template - static auto unmap_page_table_entry(T & allocator, virtual_page page, page_table_handle & handle) -> void - { - auto level_index = page.get_level_index(handle.get_level()); - auto & entry = handle[level_index]; - auto const frame = entry.calculate_pointed_to_frame(); - exception_handling::assert(frame.has_value(), - "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); - entry.set_unused(); - allocator.deallocate_frame(frame.value()); - } + static auto unmap_page_table_entry(allocator::frame_allocator & allocator, virtual_page page, + page_table_handle & handle) -> void; public: page_table_handle active_handle; ///< Underlying active level 4 page table diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index f980451..2f55a13 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -1,11 +1,11 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP -#include "arch/memory/cpu/control_register.hpp" +#include "arch/memory/allocator/frame_allocator.hpp" +#include "arch/memory/multiboot/reader.hpp" #include "arch/memory/paging/active_page_table.hpp" #include "arch/memory/paging/inactive_page_table.hpp" #include "arch/memory/paging/temporary_page.hpp" -#include "arch/video/vga/text.hpp" namespace teachos::arch::memory::paging { @@ -14,7 +14,6 @@ namespace teachos::arch::memory::paging * * @tparam T Contract the allocator that should be used to allocate frames for the remapping process has to fulfill. */ - template struct kernel_mapper { /** @@ -23,12 +22,7 @@ namespace teachos::arch::memory::paging * @param allocator Allocator that should be used to allocate frames for the remapping process. * @param mem_info Information about elf kernel sections required for remapping process. */ - kernel_mapper(T & allocator, multiboot::memory_information const & mem_info) - : allocator(allocator) - , mem_info(mem_info) - { - // Nothing to do - } + kernel_mapper(allocator::frame_allocator & allocator, multiboot::memory_information const & mem_info); /** * @brief Remap the kernel, meaning we map the entire kernel and all of it's elf sections with the correct flags @@ -38,21 +32,7 @@ namespace teachos::arch::memory::paging * inactive page table, that is not used by the CPU to ensure we are not changign memory that we are using. Because * remapping active kernel memory in the kernel wouldn't work. */ - auto remap_kernel() -> active_page_table & - { - temporary_page temporary_page{virtual_page{0xCAFEBABE}, allocator}; - auto & active_table = active_page_table::create_or_get(); - auto const frame = allocator.allocate_frame(); - exception_handling::assert(frame.has_value(), - "[Kernel Mapper] Frame could not be allocated and therefore kernel not mapped"); - inactive_page_table new_table{frame.value(), active_table, temporary_page}; - remap_elf_kernel_sections(new_table, temporary_page, active_table); - auto const old_table = switch_active_page_table(new_table); - auto const old_level_4_page = - virtual_page::containing_address(old_table.page_table_level_4_frame.start_address()); - active_table.unmap_page(allocator, old_level_4_page); - return active_table; - } + auto remap_kernel() -> active_page_table &; private: /** @@ -63,8 +43,8 @@ namespace teachos::arch::memory::paging * Once the remapping process is done we can restore the original recursive mapping with the complete remapped * kernel. * - * @note Because we change the entries we also have to ensure we flush the translation lookaside buffer, before we - * map the entries. + * @note Because we change the entries we also have to ensure we flush the translation lookaside buffer, before + * we map the entries. * * @param inactive_table Level 4 page table we temporarily map the kernel into. * @param temporary_page Temporary page that should be used for the mapping process and then @@ -73,20 +53,7 @@ namespace teachos::arch::memory::paging * restored once the process is finished. */ auto remap_elf_kernel_sections(inactive_page_table & inactive_table, temporary_page & temporary_page, - active_page_table & active_table) -> void - { - auto const backup = - allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3)); - auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); - - active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); - cpu::tlb_flush_all(); - map_elf_kernel_sections(active_table); - - page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); - cpu::tlb_flush_all(); - temporary_page.unmap_page(active_table); - } + active_page_table & active_table) -> void; /** * @brief Switches the current active table pointed to by the CR3 register with another page table that is currently @@ -95,16 +62,7 @@ namespace teachos::arch::memory::paging * @param new_table Inactive page table that should now be made active and replace the current active one. * @return The previous active page table. */ - auto switch_active_page_table(inactive_page_table new_table) -> inactive_page_table - { - auto const backup = - allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3)); - auto const old_table = inactive_page_table{backup}; - - auto const new_address = new_table.page_table_level_4_frame.start_address(); - cpu::write_control_register(cpu::control_register::CR3, new_address); - return old_table; - } + auto switch_active_page_table(inactive_page_table new_table) -> inactive_page_table; /** * @brief Maps the required entries according to every elf section and it's contained frames. Additionally each of @@ -113,41 +71,9 @@ namespace teachos::arch::memory::paging * @param active_table Active level 4 page table that should be used to map the required elf sections into entries. * Has had its recursive mapping temporarily replaced and points to unmapped place in memory. */ - auto map_elf_kernel_sections(active_page_table & active_table) -> void - { - exception_handling::assert(!mem_info.sections.empty(), "[Kernel Mapper] Kernel elf sections empty"); - for (auto const & section : mem_info.sections) - { - if (!section.flags.contains_flags(multiboot::elf_section_flags::OCCUPIES_MEMORY)) - { - continue; - } - exception_handling::assert(section.physical_address % allocator::PAGE_FRAME_SIZE == 0U, - "[Kernel Mapper] Section must be page aligned"); - auto const start_frame = allocator::physical_frame::containing_address(section.physical_address); - // End address is exclusive, so that it is not part of the section anymore (one past the last frame of this - // section). But end frame would now point to the actual last frame and not one past the last frame, therefore - // we increment by one to get one past the last frame of this section. - auto const end_frame = - ++(allocator::physical_frame::containing_address(section.physical_address + section.section_size - 1)); - - allocator::frame_container::iterator const begin{start_frame}; - allocator::frame_container::iterator const end{end_frame}; - allocator::frame_container const frames{begin, end}; - entry const entry{section.flags}; - - for (auto const & frame : frames) - { - active_table.identity_map(allocator, frame, entry.get_flags()); - } - } - - auto const vga_buffer_frame = - allocator::physical_frame::containing_address(video::vga::text::DEFAULT_VGA_TEXT_BUFFER_ADDRESS); - active_table.identity_map(allocator, vga_buffer_frame, entry::WRITABLE); - } + auto map_elf_kernel_sections(active_page_table & active_table) -> void; - T & allocator; + allocator::frame_allocator & allocator; multiboot::memory_information const & mem_info; ///< Information about elf kernel sections required for remapping process. }; diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 7a15875..24ff8f4 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -2,7 +2,7 @@ #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP #include "arch/exception_handling/assert.hpp" -#include "arch/memory/allocator/concept.hpp" +#include "arch/memory/allocator/frame_allocator.hpp" #include "arch/memory/paging/page_entry.hpp" namespace teachos::arch::memory::paging @@ -82,26 +82,7 @@ namespace teachos::arch::memory::paging * entries when a new page table is required. * @param table_index Index of this page table in the page table one level lower. */ - template - auto next_table_or_create(T & allocator, std::size_t table_index) -> page_table_handle - { - auto next_handle = next_table(table_index); - // If the next table method failed then it means that the page level of the frame we want allocate has not yet - // been created itself. So we have to do that before we are able to allocate the wanted frame. This has to be done - // for every level, meaning we potenitally create a level 4, level 3 and level 2 page entry, each pointing to a - // page table one level below. - if (!next_handle.has_value()) - { - auto const allocated_frame = allocator.allocate_frame(); - exception_handling::assert(allocated_frame.has_value(), "[Page mapper] Unable to allocate frame"); - this->operator[](table_index).set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); - // There should now be an entry at the previously not existent index, therefore we can simply access it again. - next_handle = next_table(table_index); - exception_handling::assert(next_handle.has_value(), "[Page mapper] Unable to create new entry into page table"); - next_handle.value().zero_entries(); - } - return next_handle.value(); - } + auto next_table_or_create(allocator::frame_allocator & allocator, std::size_t table_index) -> page_table_handle; /** * @brief Index operator overload to access specific mutable entry directy. diff --git a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp index a850879..3c4301a 100644 --- a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp @@ -20,13 +20,7 @@ namespace teachos::arch::memory::paging * @param page Page to turn into temporary page * @param allocator Frame allocator used to fill page */ - template - temporary_page(virtual_page page, T & allocator) - : page{page} - , allocator{allocator} - { - // Nothing to do - } + temporary_page(virtual_page page, allocator::frame_allocator & allocator); /** * @brief Unmap the current page. -- cgit v1.2.3 From 4c44f822eefa743649693e0a49a978291925ddff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 24 Nov 2024 09:17:53 +0000 Subject: Revert: de-templatize paging implementation --- .../arch/memory/allocator/area_frame_allocator.hpp | 7 +- .../include/arch/memory/allocator/concept.hpp | 22 +++++ .../arch/memory/allocator/frame_allocator.hpp | 19 ----- .../arch/memory/allocator/tiny_frame_allocator.hpp | 32 ++++++-- .../arch/memory/paging/active_page_table.hpp | 82 ++++++++++++++++--- .../include/arch/memory/paging/kernel_mapper.hpp | 94 +++++++++++++++++++--- .../include/arch/memory/paging/page_table.hpp | 23 +++++- .../include/arch/memory/paging/temporary_page.hpp | 17 ++-- 8 files changed, 236 insertions(+), 60 deletions(-) create mode 100644 arch/x86_64/include/arch/memory/allocator/concept.hpp delete mode 100644 arch/x86_64/include/arch/memory/allocator/frame_allocator.hpp (limited to 'arch/x86_64/include') 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 f1a3a64..adba4f1 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,7 +1,6 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP #define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP -#include "arch/memory/allocator/frame_allocator.hpp" #include "arch/memory/allocator/physical_frame.hpp" #include "arch/memory/multiboot/reader.hpp" @@ -12,7 +11,7 @@ namespace teachos::arch::memory::allocator /** * @brief Allocates memory using memory areas read from the multiboot2 information pointer. */ - struct area_frame_allocator : frame_allocator + struct area_frame_allocator { /** * @brief Constructor @@ -33,7 +32,7 @@ namespace teachos::arch::memory::allocator * * @return next free physical frame or nullopt if none was found. */ - auto allocate_frame() -> std::optional override; + auto allocate_frame() -> std::optional; /** * @brief Deallocates a previously allocated physical frame. @@ -44,7 +43,7 @@ namespace teachos::arch::memory::allocator * * @param physical_frame Previously allocated physical_frame that should be deallocated. */ - auto deallocate_frame(physical_frame const & physical_frame) -> void override; + auto deallocate_frame(physical_frame const & physical_frame) -> void; private: /** diff --git a/arch/x86_64/include/arch/memory/allocator/concept.hpp b/arch/x86_64/include/arch/memory/allocator/concept.hpp new file mode 100644 index 0000000..9d58fad --- /dev/null +++ b/arch/x86_64/include/arch/memory/allocator/concept.hpp @@ -0,0 +1,22 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_CONCEPT_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_CONCEPT_HPP + +#include "arch/memory/allocator/physical_frame.hpp" + +#include + +namespace teachos::arch::memory::allocator +{ + /** + * @brief Frame allocator concept + * + * @tparam T + */ + template + concept FrameAllocator = requires(T t, physical_frame const & a) { + { t.allocate_frame() } -> std::same_as>; + { t.deallocate_frame(a) } -> std::same_as; + }; +} // namespace teachos::arch::memory::allocator + +#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_CONCEPT_HPP diff --git a/arch/x86_64/include/arch/memory/allocator/frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/frame_allocator.hpp deleted file mode 100644 index 9316ca9..0000000 --- a/arch/x86_64/include/arch/memory/allocator/frame_allocator.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_FRAME_ALLOCATOR_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_FRAME_ALLOCATOR_HPP - -#include "arch/memory/allocator/physical_frame.hpp" - -#include - -namespace teachos::arch::memory::allocator -{ - - struct frame_allocator - { - auto virtual allocate_frame() -> std::optional = 0; - auto virtual deallocate_frame(physical_frame const & frame) -> void = 0; - }; // namespace teachos::arch::memory::allocator - -} // namespace teachos::arch::memory::allocator - -#endif \ No newline at end of file diff --git a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp index c449ac8..8124442 100644 --- a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp @@ -1,7 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP #define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP -#include "arch/memory/allocator/frame_allocator.hpp" +#include "arch/memory/allocator/concept.hpp" #include "arch/memory/allocator/physical_frame.hpp" #include @@ -16,17 +16,33 @@ namespace teachos::arch::memory::allocator /** * @brief Allocates memory using memory areas read from the multiboot2 information pointer. */ - struct tiny_frame_allocator : frame_allocator + struct tiny_frame_allocator { /** * @brief Constructor. * - * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and - * deallocate method. + * @tparam T Contract the allocator that should be used to actually allocate and deallocate, the underlying three + * frames has to follow. + * * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate - * entries *when a new page table is required. + * entries when the underlying frames are created. */ - tiny_frame_allocator(frame_allocator & allocator); + template + tiny_frame_allocator(T & allocator) + : frames{} + { + // Has to be done this way, because constructing the constructor with the data from allocator.allocate_frames(), + // does not work because it would set the value correctly but because we pass it as an std::optional it would not + // set the engaged flag. Meaning the has_value() method would still return false. + for (auto & frame : frames) + { + auto allocated = allocator.allocate_frame(); + if (allocated.has_value()) + { + frame.emplace(allocated.value()); + } + } + } /** * @brief Allocate memory by finding and returning one of the three free physical frames. @@ -34,7 +50,7 @@ namespace teachos::arch::memory::allocator * @return First free physical frames of the three frames held by this allocator or nullopt if we used up all three * frames already. */ - auto allocate_frame() -> std::optional override; + auto allocate_frame() -> std::optional; /** * @brief Deallocates one of the three previously allocated physical frames. @@ -44,7 +60,7 @@ namespace teachos::arch::memory::allocator * * @param physical_frame Previously allocated physical_frame that should be deallocated. */ - auto deallocate_frame(physical_frame const & physical_frame) -> void override; + auto deallocate_frame(physical_frame const & physical_frame) -> void; private: std::array, TINY_ALLOCATOR_FRAMES_COUNT> frames = diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index e558fa5..88c1c82 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -1,9 +1,9 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_ACTIVE_PAGE_TABLE_HPP #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_ACTIVE_PAGE_TABLE_HPP -#include "arch/memory/allocator/frame_allocator.hpp" -#include "arch/memory/allocator/physical_frame.hpp" -#include "arch/memory/paging/page_table.hpp" +#include "arch/exception_handling/assert.hpp" +#include "arch/memory/allocator/concept.hpp" +#include "arch/memory/cpu/tlb.hpp" #include "arch/memory/paging/virtual_page.hpp" #include @@ -66,21 +66,44 @@ namespace teachos::arch::memory::paging * @note Allocates and maps an entry in every page level if it does not exists yet down to level 1. If the level 1 * page table already exists it halts execution instead. * + * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and + * deallocate method. * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate * entries when a new page table is required. * @param page Virtual page that is being mapped. * @param frame Physical frame that the virtual page will be mapped to. * @param flags A bitset of flags that configure the page table entry for this mapping. */ - auto map_page_to_frame(allocator::frame_allocator & allocator, virtual_page page, allocator::physical_frame frame, - std::bitset<64U> flags) -> void; + template + auto map_page_to_frame(T & allocator, virtual_page page, allocator::physical_frame frame, + std::bitset<64U> flags) -> void + { + auto current_handle = active_handle; + + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) + { + current_handle = current_handle.next_table_or_create(allocator, page.get_level_index(level)); + } + + auto & level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; + arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE), + "[Page Mapper] Unable to map huge pages"); + arch::exception_handling::assert(level1_entry.is_unused(), "[Page Mapper] Page table entry is already used"); + level1_entry.set_entry(frame, flags.to_ulong() | entry::PRESENT); + } + /** * @brief Allocates the next free frame and then uses that frame to call map_page_to_frame. * * @see map_page_to_frame */ - auto map_next_free_page_to_frame(allocator::frame_allocator & allocator, virtual_page page, - std::bitset<64U> flags) -> void; + template + auto map_next_free_page_to_frame(T & allocator, virtual_page page, std::bitset<64U> flags) -> void + { + auto const frame = allocator.allocate_frame(); + exception_handling::assert(frame.has_value(), "[Page mapper] Out of memory exception"); + map_page_to_frame(allocator, page, frame.value(), flags); + } /** * @brief Gets the corresponding page the given frame has to be contained in and uses that to call @@ -88,8 +111,12 @@ namespace teachos::arch::memory::paging * * @see map_page_to_frame */ - auto identity_map(allocator::frame_allocator & allocator, allocator::physical_frame frame, - std::bitset<64U> flags) -> void; + template + auto identity_map(T & allocator, allocator::physical_frame frame, std::bitset<64U> flags) -> void + { + auto const page = virtual_page::containing_address(frame.start_address()); + map_page_to_frame(allocator, page, frame, flags); + } /** * @brief Unmaps the virtual page from the previously mapped to physical frame and resets the flags. @@ -103,7 +130,27 @@ namespace teachos::arch::memory::paging * entries when a new page table is required. * @param page Virtual page that is being unmapped. */ - auto unmap_page(allocator::frame_allocator & allocator, virtual_page page) -> void; + template + auto unmap_page(T & allocator, virtual_page page) -> void + { + exception_handling::assert(translate_page(page).has_value(), + "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); + + auto current_handle = active_handle; + + for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) + { + auto const level_index = page.get_level_index(level); + auto const next_handle = current_handle.next_table(level_index); + // The next table method failed even tough the page has to be mapped already, because translate_page did not + // fail. This can only mean that we attempted to unmap a huge page, which is not supported in the first place. + exception_handling::assert(next_handle.has_value(), "[Page Mapper] Unable to unmap huge pages"); + current_handle = next_handle.value(); + } + + unmap_page_table_entry(allocator, page, current_handle); + cpu::tlb_flush(page.start_address()); + } private: /** @@ -127,13 +174,24 @@ namespace teachos::arch::memory::paging /** * @brief Unmaps specific page at the current internal handle level. * + * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and + * deallocate method. * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate * entries *when a new page table is required. * @param page Virtual page that is being unmapped. * @param handle Page Table handle we want to access the entry that should be cleared on. */ - static auto unmap_page_table_entry(allocator::frame_allocator & allocator, virtual_page page, - page_table_handle & handle) -> void; + template + static auto unmap_page_table_entry(T & allocator, virtual_page page, page_table_handle & handle) -> void + { + auto level_index = page.get_level_index(handle.get_level()); + auto & entry = handle[level_index]; + auto const frame = entry.calculate_pointed_to_frame(); + exception_handling::assert(frame.has_value(), + "[Page Mapper] Attempted to unmap page, which has not been mapped previously"); + entry.set_unused(); + allocator.deallocate_frame(frame.value()); + } public: page_table_handle active_handle; ///< Underlying active level 4 page table diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 2f55a13..f980451 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -1,11 +1,11 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP -#include "arch/memory/allocator/frame_allocator.hpp" -#include "arch/memory/multiboot/reader.hpp" +#include "arch/memory/cpu/control_register.hpp" #include "arch/memory/paging/active_page_table.hpp" #include "arch/memory/paging/inactive_page_table.hpp" #include "arch/memory/paging/temporary_page.hpp" +#include "arch/video/vga/text.hpp" namespace teachos::arch::memory::paging { @@ -14,6 +14,7 @@ namespace teachos::arch::memory::paging * * @tparam T Contract the allocator that should be used to allocate frames for the remapping process has to fulfill. */ + template struct kernel_mapper { /** @@ -22,7 +23,12 @@ namespace teachos::arch::memory::paging * @param allocator Allocator that should be used to allocate frames for the remapping process. * @param mem_info Information about elf kernel sections required for remapping process. */ - kernel_mapper(allocator::frame_allocator & allocator, multiboot::memory_information const & mem_info); + kernel_mapper(T & allocator, multiboot::memory_information const & mem_info) + : allocator(allocator) + , mem_info(mem_info) + { + // Nothing to do + } /** * @brief Remap the kernel, meaning we map the entire kernel and all of it's elf sections with the correct flags @@ -32,7 +38,21 @@ namespace teachos::arch::memory::paging * inactive page table, that is not used by the CPU to ensure we are not changign memory that we are using. Because * remapping active kernel memory in the kernel wouldn't work. */ - auto remap_kernel() -> active_page_table &; + auto remap_kernel() -> active_page_table & + { + temporary_page temporary_page{virtual_page{0xCAFEBABE}, allocator}; + auto & active_table = active_page_table::create_or_get(); + auto const frame = allocator.allocate_frame(); + exception_handling::assert(frame.has_value(), + "[Kernel Mapper] Frame could not be allocated and therefore kernel not mapped"); + inactive_page_table new_table{frame.value(), active_table, temporary_page}; + remap_elf_kernel_sections(new_table, temporary_page, active_table); + auto const old_table = switch_active_page_table(new_table); + auto const old_level_4_page = + virtual_page::containing_address(old_table.page_table_level_4_frame.start_address()); + active_table.unmap_page(allocator, old_level_4_page); + return active_table; + } private: /** @@ -43,8 +63,8 @@ namespace teachos::arch::memory::paging * Once the remapping process is done we can restore the original recursive mapping with the complete remapped * kernel. * - * @note Because we change the entries we also have to ensure we flush the translation lookaside buffer, before - * we map the entries. + * @note Because we change the entries we also have to ensure we flush the translation lookaside buffer, before we + * map the entries. * * @param inactive_table Level 4 page table we temporarily map the kernel into. * @param temporary_page Temporary page that should be used for the mapping process and then @@ -53,7 +73,20 @@ namespace teachos::arch::memory::paging * restored once the process is finished. */ auto remap_elf_kernel_sections(inactive_page_table & inactive_table, temporary_page & temporary_page, - active_page_table & active_table) -> void; + active_page_table & active_table) -> void + { + auto const backup = + allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3)); + auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); + + active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); + cpu::tlb_flush_all(); + map_elf_kernel_sections(active_table); + + page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); + cpu::tlb_flush_all(); + temporary_page.unmap_page(active_table); + } /** * @brief Switches the current active table pointed to by the CR3 register with another page table that is currently @@ -62,7 +95,16 @@ namespace teachos::arch::memory::paging * @param new_table Inactive page table that should now be made active and replace the current active one. * @return The previous active page table. */ - auto switch_active_page_table(inactive_page_table new_table) -> inactive_page_table; + auto switch_active_page_table(inactive_page_table new_table) -> inactive_page_table + { + auto const backup = + allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3)); + auto const old_table = inactive_page_table{backup}; + + auto const new_address = new_table.page_table_level_4_frame.start_address(); + cpu::write_control_register(cpu::control_register::CR3, new_address); + return old_table; + } /** * @brief Maps the required entries according to every elf section and it's contained frames. Additionally each of @@ -71,9 +113,41 @@ namespace teachos::arch::memory::paging * @param active_table Active level 4 page table that should be used to map the required elf sections into entries. * Has had its recursive mapping temporarily replaced and points to unmapped place in memory. */ - auto map_elf_kernel_sections(active_page_table & active_table) -> void; + auto map_elf_kernel_sections(active_page_table & active_table) -> void + { + exception_handling::assert(!mem_info.sections.empty(), "[Kernel Mapper] Kernel elf sections empty"); + for (auto const & section : mem_info.sections) + { + if (!section.flags.contains_flags(multiboot::elf_section_flags::OCCUPIES_MEMORY)) + { + continue; + } + exception_handling::assert(section.physical_address % allocator::PAGE_FRAME_SIZE == 0U, + "[Kernel Mapper] Section must be page aligned"); + auto const start_frame = allocator::physical_frame::containing_address(section.physical_address); + // End address is exclusive, so that it is not part of the section anymore (one past the last frame of this + // section). But end frame would now point to the actual last frame and not one past the last frame, therefore + // we increment by one to get one past the last frame of this section. + auto const end_frame = + ++(allocator::physical_frame::containing_address(section.physical_address + section.section_size - 1)); + + allocator::frame_container::iterator const begin{start_frame}; + allocator::frame_container::iterator const end{end_frame}; + allocator::frame_container const frames{begin, end}; + entry const entry{section.flags}; + + for (auto const & frame : frames) + { + active_table.identity_map(allocator, frame, entry.get_flags()); + } + } + + auto const vga_buffer_frame = + allocator::physical_frame::containing_address(video::vga::text::DEFAULT_VGA_TEXT_BUFFER_ADDRESS); + active_table.identity_map(allocator, vga_buffer_frame, entry::WRITABLE); + } - allocator::frame_allocator & allocator; + T & allocator; multiboot::memory_information const & mem_info; ///< Information about elf kernel sections required for remapping process. }; diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 24ff8f4..7a15875 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -2,7 +2,7 @@ #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP #include "arch/exception_handling/assert.hpp" -#include "arch/memory/allocator/frame_allocator.hpp" +#include "arch/memory/allocator/concept.hpp" #include "arch/memory/paging/page_entry.hpp" namespace teachos::arch::memory::paging @@ -82,7 +82,26 @@ namespace teachos::arch::memory::paging * entries when a new page table is required. * @param table_index Index of this page table in the page table one level lower. */ - auto next_table_or_create(allocator::frame_allocator & allocator, std::size_t table_index) -> page_table_handle; + template + auto next_table_or_create(T & allocator, std::size_t table_index) -> page_table_handle + { + auto next_handle = next_table(table_index); + // If the next table method failed then it means that the page level of the frame we want allocate has not yet + // been created itself. So we have to do that before we are able to allocate the wanted frame. This has to be done + // for every level, meaning we potenitally create a level 4, level 3 and level 2 page entry, each pointing to a + // page table one level below. + if (!next_handle.has_value()) + { + auto const allocated_frame = allocator.allocate_frame(); + exception_handling::assert(allocated_frame.has_value(), "[Page mapper] Unable to allocate frame"); + this->operator[](table_index).set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); + // There should now be an entry at the previously not existent index, therefore we can simply access it again. + next_handle = next_table(table_index); + exception_handling::assert(next_handle.has_value(), "[Page mapper] Unable to create new entry into page table"); + next_handle.value().zero_entries(); + } + return next_handle.value(); + } /** * @brief Index operator overload to access specific mutable entry directy. diff --git a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp index 3c4301a..02cb545 100644 --- a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp @@ -14,13 +14,20 @@ namespace teachos::arch::memory::paging struct temporary_page { /** - * @brief Construct a new temporary page object + * @brief Construct a new temporary page object. * - * @tparam FrameAllocator concept - * @param page Page to turn into temporary page - * @param allocator Frame allocator used to fill page + * @tparam Type constraint of the allocator, being that is follows the given concept and contains an allocate and + * deallocate method. + * @param page Page to turn into temporary page. + * @param allocator Frame allocator used to fill page. */ - temporary_page(virtual_page page, allocator::frame_allocator & allocator); + template + temporary_page(virtual_page page, T & allocator) + : page{page} + , allocator{allocator} + { + // Nothing to do + } /** * @brief Unmap the current page. -- cgit v1.2.3 From 641f20fd782deb6d9e1e1b9996005ad893028744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 24 Nov 2024 09:22:23 +0000 Subject: Adjust notes on actual unmap implementation --- arch/x86_64/include/arch/memory/paging/active_page_table.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index 88c1c82..4687209 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -121,8 +121,12 @@ namespace teachos::arch::memory::paging /** * @brief Unmaps the virtual page from the previously mapped to physical frame and resets the flags. * - * @note Deallocates and unmaps the entry in every page level if this page was the last one up to level 4 and - * ensures to clear the Translation Lookaside Buffer, so that the unmapped value is removed from cache as well. + * @note For the unmap function to deallocates and unmaps correctly, the entry in every page level if this page was + * the last one up to level 4 should be unmapped and ensured to clear the Translation Lookaside Buffer, so that the + * unmapped value is removed from cache as well. This is currently not done and instead we only dallocate and unmap + * the level 1 page table entry, this is the case because it conflicts with our recursive mapping for the temporary + * page, which requires the other page table entries to walk to the actual level 4 page table. If we remove all page + * table entries beforehand, we therefore can not remap the kernel anymore. * * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and * deallocate method. -- cgit v1.2.3 From 77146c6e2dbd02661636d9424b7e51562eac30c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 24 Nov 2024 09:44:41 +0000 Subject: Add notes on missing features for kernel remapping --- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index f980451..897ae06 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -48,6 +48,8 @@ namespace teachos::arch::memory::paging inactive_page_table new_table{frame.value(), active_table, temporary_page}; remap_elf_kernel_sections(new_table, temporary_page, active_table); auto const old_table = switch_active_page_table(new_table); + // Turn old level 4 page table, mapped by assembler code into stack guard page. + // Only works if the identity mapped page tables by assembler are right above the stack. auto const old_level_4_page = virtual_page::containing_address(old_table.page_table_level_4_frame.start_address()); active_table.unmap_page(allocator, old_level_4_page); -- cgit v1.2.3 From 55f32173e97fdcf4a45006b66cc4b20329a5c7af Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 24 Nov 2024 13:10:21 +0000 Subject: implement basic heap and remap it --- arch/x86_64/include/arch/memory/heap/allocator.hpp | 32 ++++++++++++++++++++++ arch/x86_64/include/arch/memory/heap/concept.hpp | 15 ++++++++++ arch/x86_64/include/arch/memory/main.hpp | 13 +++++++++ .../arch/memory/paging/active_page_table.hpp | 2 +- 4 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 arch/x86_64/include/arch/memory/heap/allocator.hpp create mode 100644 arch/x86_64/include/arch/memory/heap/concept.hpp create mode 100644 arch/x86_64/include/arch/memory/main.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/allocator.hpp b/arch/x86_64/include/arch/memory/heap/allocator.hpp new file mode 100644 index 0000000..c486a4c --- /dev/null +++ b/arch/x86_64/include/arch/memory/heap/allocator.hpp @@ -0,0 +1,32 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_ALLOCATOR_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_ALLOCATOR_HPP + +#include + +namespace teachos::arch::memory::heap +{ + std::size_t constexpr HEAP_START = 0x4000'0000; + std::size_t constexpr HEAP_SIZE = 100 * 1024; + + struct bump_allocator + { + bump_allocator(std::size_t heap_start, std::size_t heap_end) + : heap_start{heap_start} + , heap_end{heap_end} + , next{heap_start} + { + } + + auto allocate(std::size_t size) -> void *; + + auto deallocate(uint8_t * pointer, std::size_t size) -> void; + + private: + std::size_t heap_start; + std::size_t heap_end; + std::size_t next; + }; + +} // namespace teachos::arch::memory::heap + +#endif \ No newline at end of file diff --git a/arch/x86_64/include/arch/memory/heap/concept.hpp b/arch/x86_64/include/arch/memory/heap/concept.hpp new file mode 100644 index 0000000..a525b0b --- /dev/null +++ b/arch/x86_64/include/arch/memory/heap/concept.hpp @@ -0,0 +1,15 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_CONCEPT_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_CONCEPT_HPP + +#include + +namespace teachos::arch::memory::heap +{ + template + concept HeapAllocator = requires(T t, uint8_t * pointer, std::size_t size) { + { t.allocate(size) } -> std::same_as; + { t.deallocate(pointer, size) } -> std::same_as; + }; +} // namespace teachos::arch::memory::heap + +#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_CONCEPT_HPP \ No newline at end of file diff --git a/arch/x86_64/include/arch/memory/main.hpp b/arch/x86_64/include/arch/memory/main.hpp new file mode 100644 index 0000000..e166285 --- /dev/null +++ b/arch/x86_64/include/arch/memory/main.hpp @@ -0,0 +1,13 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_MAIN_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_MAIN_HPP + +namespace teachos::arch::memory +{ + /** + * @brief + * + */ + auto initialize_memory_management() -> void; +} // namespace teachos::arch::memory + +#endif diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index 4687209..1b2aaed 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -98,7 +98,7 @@ namespace teachos::arch::memory::paging * @see map_page_to_frame */ template - auto map_next_free_page_to_frame(T & allocator, virtual_page page, std::bitset<64U> flags) -> void + auto map_page_to_next_free_frame(T & allocator, virtual_page page, std::bitset<64U> flags) -> void { auto const frame = allocator.allocate_frame(); exception_handling::assert(frame.has_value(), "[Page mapper] Out of memory exception"); -- cgit v1.2.3 From 24805678884bcfcc3f14e88757955ab574d647cb Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 24 Nov 2024 13:18:31 +0000 Subject: add doxygen comments to remapping --- arch/x86_64/include/arch/memory/heap/allocator.hpp | 16 +++++++++++++++- arch/x86_64/include/arch/memory/main.hpp | 4 +++- 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/allocator.hpp b/arch/x86_64/include/arch/memory/heap/allocator.hpp index c486a4c..6f7535e 100644 --- a/arch/x86_64/include/arch/memory/heap/allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/allocator.hpp @@ -8,6 +8,9 @@ namespace teachos::arch::memory::heap std::size_t constexpr HEAP_START = 0x4000'0000; std::size_t constexpr HEAP_SIZE = 100 * 1024; + /** + * @brief Simple heap allocator + */ struct bump_allocator { bump_allocator(std::size_t heap_start, std::size_t heap_end) @@ -17,9 +20,20 @@ namespace teachos::arch::memory::heap { } + /** + * @brief Allocates the specified amount of memory in the heap + * + * @param size Amount of memory to allocate + * @return Address of the allocated memory + */ auto allocate(std::size_t size) -> void *; - auto deallocate(uint8_t * pointer, std::size_t size) -> void; + /** + * @brief Deallocates heap memory at the specified location + * + * @param pointer Pointer to the location which should be deallocated + */ + auto deallocate(uint8_t * pointer) -> void; private: std::size_t heap_start; diff --git a/arch/x86_64/include/arch/memory/main.hpp b/arch/x86_64/include/arch/memory/main.hpp index e166285..bbf160b 100644 --- a/arch/x86_64/include/arch/memory/main.hpp +++ b/arch/x86_64/include/arch/memory/main.hpp @@ -4,8 +4,10 @@ namespace teachos::arch::memory { /** - * @brief + * @brief Initializes memory management * + * @note Enables the necessary register flags and remaps the kernel, + * elf_sections, vga_text and the heap. */ auto initialize_memory_management() -> void; } // namespace teachos::arch::memory -- cgit v1.2.3 From 47732f54474a083e9f98e52714c12c0ca1181174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 24 Nov 2024 13:27:15 +0000 Subject: Use container helper classes for heap remapping --- .../arch/memory/allocator/physical_frame.hpp | 4 ++-- .../include/arch/memory/paging/virtual_page.hpp | 23 +++++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp index a39517a..d5e2f4c 100644 --- a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp +++ b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp @@ -54,14 +54,14 @@ namespace teachos::arch::memory::allocator /** * @brief Post increment operator. Returns a copy of the value. * - * @return Copy of the incremented underlying address. + * @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 address. + * @return Reference to the incremented underlying frame number. */ auto operator++() -> physical_frame &; diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index c319af2..0ee9cbd 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -17,6 +17,11 @@ namespace teachos::arch::memory::paging */ struct virtual_page { + /** + * @brief Defaulted constructor. + */ + constexpr virtual_page() = default; + /** * @brief Constructor. * @@ -51,6 +56,20 @@ namespace teachos::arch::memory::paging */ auto get_level_index(page_table_handle::level level) const -> size_t; + /** + * @brief Post increment operator. Returns a copy of the value. + * + * @return Copy of the incremented underlying page number. + */ + auto operator++(int) -> virtual_page; + + /** + * @brief Pre increment operator. Returns a reference to the changed value. + * + * @return Reference to the incremented underlying page number. + */ + auto operator++() -> virtual_page &; + /** * @brief Defaulted equals operator. */ @@ -61,9 +80,11 @@ namespace teachos::arch::memory::paging */ auto operator<=>(const virtual_page & other) const -> std::partial_ordering = default; - std::size_t page_number; ///< Index number of the current virtual page, used to distinguish it from other pages. + std::size_t page_number = + {}; ///< Index number of the current virtual page, used to distinguish it from other pages. }; + typedef shared::container> page_container; } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP -- cgit v1.2.3 From c291e1ed629489c418049f6c4116433636717636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 24 Nov 2024 13:51:12 +0000 Subject: Add comments and rename file --- arch/x86_64/include/arch/memory/heap/allocator.hpp | 46 ------------------- .../include/arch/memory/heap/bump_allocator.hpp | 53 ++++++++++++++++++++++ arch/x86_64/include/arch/memory/heap/concept.hpp | 7 ++- 3 files changed, 58 insertions(+), 48 deletions(-) delete mode 100644 arch/x86_64/include/arch/memory/heap/allocator.hpp create mode 100644 arch/x86_64/include/arch/memory/heap/bump_allocator.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/allocator.hpp b/arch/x86_64/include/arch/memory/heap/allocator.hpp deleted file mode 100644 index 6f7535e..0000000 --- a/arch/x86_64/include/arch/memory/heap/allocator.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_ALLOCATOR_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_ALLOCATOR_HPP - -#include - -namespace teachos::arch::memory::heap -{ - std::size_t constexpr HEAP_START = 0x4000'0000; - std::size_t constexpr HEAP_SIZE = 100 * 1024; - - /** - * @brief Simple heap allocator - */ - struct bump_allocator - { - bump_allocator(std::size_t heap_start, std::size_t heap_end) - : heap_start{heap_start} - , heap_end{heap_end} - , next{heap_start} - { - } - - /** - * @brief Allocates the specified amount of memory in the heap - * - * @param size Amount of memory to allocate - * @return Address of the allocated memory - */ - auto allocate(std::size_t size) -> void *; - - /** - * @brief Deallocates heap memory at the specified location - * - * @param pointer Pointer to the location which should be deallocated - */ - auto deallocate(uint8_t * pointer) -> void; - - private: - std::size_t heap_start; - std::size_t heap_end; - std::size_t next; - }; - -} // namespace teachos::arch::memory::heap - -#endif \ No newline at end of file diff --git a/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp b/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp new file mode 100644 index 0000000..5b581ba --- /dev/null +++ b/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp @@ -0,0 +1,53 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_BUMP_ALLOCATOR_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_BUMP_ALLOCATOR_HPP + +#include + +namespace teachos::arch::memory::heap +{ + /** + * @brief Simple heap allocator, which leaks all allocated memory, because it does not really deallocate anything. + */ + struct bump_allocator + { + /** + * @brief Constructor. + * + * @param heap_start Start of the allocatable heap area + * @param heap_end End of the allocatable heap area (Start + Size) + */ + bump_allocator(std::size_t heap_start, std::size_t heap_end) + : heap_start{heap_start} + , heap_end{heap_end} + , next{heap_start} + { + // Nothing to do + } + + /** + * @brief Allocates the specified amount of memory in the heap. + * + * @param size Amount of memory to allocate. + * @return Address of the first byte to the allocated area + */ + auto allocate(std::size_t size) -> void *; + + /** + * @brief Deallocates heap memory at the specified location. + * + * @note Simply does nothing, because this allocator leaks all memory. + * + * @param pointer Pointer to the location which should be deallocated. + * @param size Size of the underlying memory area we want to deallocate. + */ + auto deallocate(uint8_t * pointer, std::size_t size) -> void; + + private: + std::size_t heap_start; ///< Start of the allocatable heap area + std::size_t heap_end; ///< End of the allocatable heap area + std::size_t next; ///< Current address, which is the start of still unused allocatable heap area + }; + +} // namespace teachos::arch::memory::heap + +#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_BUMP_ALLOCATOR_HPP diff --git a/arch/x86_64/include/arch/memory/heap/concept.hpp b/arch/x86_64/include/arch/memory/heap/concept.hpp index a525b0b..8c8c887 100644 --- a/arch/x86_64/include/arch/memory/heap/concept.hpp +++ b/arch/x86_64/include/arch/memory/heap/concept.hpp @@ -1,10 +1,13 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_CONCEPT_HPP #define TEACHOS_ARCH_X86_64_MEMORY_HEAP_CONCEPT_HPP -#include +#include namespace teachos::arch::memory::heap { + std::size_t constexpr HEAP_START = 0x4000'0000; + std::size_t constexpr HEAP_SIZE = 100 * 1024; + template concept HeapAllocator = requires(T t, uint8_t * pointer, std::size_t size) { { t.allocate(size) } -> std::same_as; @@ -12,4 +15,4 @@ namespace teachos::arch::memory::heap }; } // namespace teachos::arch::memory::heap -#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_CONCEPT_HPP \ No newline at end of file +#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_CONCEPT_HPP -- cgit v1.2.3 From eada7bbb150fd81e6fbf71b1df28c8dc19393cfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 24 Nov 2024 15:19:29 +0000 Subject: Adjust bump allocator comment --- arch/x86_64/include/arch/memory/heap/bump_allocator.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp b/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp index 5b581ba..d31783d 100644 --- a/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp @@ -6,7 +6,8 @@ namespace teachos::arch::memory::heap { /** - * @brief Simple heap allocator, which leaks all allocated memory, because it does not really deallocate anything. + * @brief Simple heap allocator, which allocates linearly and leaks all allocated memory, because it does not really + * deallocate anything. */ struct bump_allocator { -- cgit v1.2.3 From d2aa4fbf948a56df5328e0f1b8ec3dfd52b16e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 26 Nov 2024 09:49:06 +0000 Subject: Make bump allocator atomic and therefore thread safe --- arch/x86_64/include/arch/memory/heap/bump_allocator.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp b/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp index d31783d..595eeea 100644 --- a/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp @@ -1,6 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_BUMP_ALLOCATOR_HPP #define TEACHOS_ARCH_X86_64_MEMORY_HEAP_BUMP_ALLOCATOR_HPP +#include #include namespace teachos::arch::memory::heap @@ -44,9 +45,9 @@ namespace teachos::arch::memory::heap auto deallocate(uint8_t * pointer, std::size_t size) -> void; private: - std::size_t heap_start; ///< Start of the allocatable heap area - std::size_t heap_end; ///< End of the allocatable heap area - std::size_t next; ///< Current address, which is the start of still unused allocatable heap area + std::size_t heap_start; ///< Start of the allocatable heap area + std::size_t heap_end; ///< End of the allocatable heap area + std::atomic_uint64_t next; ///< Current address, which is the start of still unused allocatable heap area }; } // namespace teachos::arch::memory::heap -- cgit v1.2.3 From 31796138b1c85e7b3236055b6d93d568e1fe8a81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Thu, 28 Nov 2024 12:40:04 +0000 Subject: Create base of linked list allocator --- .../arch/memory/heap/linked_list_allocator.hpp | 37 ++++++++++++++++++++++ .../include/arch/memory/heap/memory_hole.hpp | 28 ++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp create mode 100644 arch/x86_64/include/arch/memory/heap/memory_hole.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp new file mode 100644 index 0000000..a742018 --- /dev/null +++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp @@ -0,0 +1,37 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_LINKED_LIST_ALLOCATOR_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_LINKED_LIST_ALLOCATOR_HPP + +#include "arch/memory/heap/memory_hole.hpp" + +#include + +namespace teachos::arch::memory::heap +{ + /** + * @brief Sorted by address list of memory holes (free memory). Uses free holes itself to save the information, + * containing the size and pointer to the next hole. Resulting in a single linked list. + */ + struct linked_list_allocator + { + /** + * @brief Constructor. + * + * @param heap_start Start of the allocatable heap area + * @param heap_end End of the allocatable heap area (Start + Size) + */ + linked_list_allocator(std::size_t heap_start, std::size_t heap_end); + + /** + * @brief Returns the smallest allocatable block of heap memory. + * + * @return Smallest allocatable block of heap memory. + */ + auto constexpr min_allocatable_size() -> std::size_t { return sizeof(memory_hole); } + + std::size_t heap_start; ///< Start of the allocatable heap area + std::size_t heap_end; ///< End of the allocatable heap area + memory_hole first; ///< First free entry in our memory + }; +} // namespace teachos::arch::memory::heap + +#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_LINKED_LIST_ALLOCATOR_HPP diff --git a/arch/x86_64/include/arch/memory/heap/memory_hole.hpp b/arch/x86_64/include/arch/memory/heap/memory_hole.hpp new file mode 100644 index 0000000..e017599 --- /dev/null +++ b/arch/x86_64/include/arch/memory/heap/memory_hole.hpp @@ -0,0 +1,28 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_HOLE_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_HOLE_HPP + +#include + +namespace teachos::arch::memory::heap +{ + /** + * @brief Block containing free memory, pointing to the next free hole (nullptr) if there is none. + * Forms a single linked list. + */ + struct memory_hole + { + /** + * @brief Constructor, + * + * @param size Amount of free memory of this specific hole. + * @param next Optional pointer to the next free memory. + */ + memory_hole(std::size_t size, memory_hole * next); + + std::size_t size; ///< Amount of free memory this hole contains, has to always be atleast 16 bytes to hold the size + ///< variable and the pointer to the next hole. + memory_hole * next; ///< Optional pointer to the next free memory, holds nullptr if there is none. + }; +} // namespace teachos::arch::memory::heap + +#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_HOLE_HPP -- cgit v1.2.3 From d3e4df4dd4ee117e247f78a86746bf178787bc8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Thu, 28 Nov 2024 13:53:01 +0000 Subject: Start with linked list alloc and dealloc --- .../arch/memory/heap/linked_list_allocator.hpp | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp index a742018..da7fc37 100644 --- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp @@ -21,6 +21,25 @@ namespace teachos::arch::memory::heap */ linked_list_allocator(std::size_t heap_start, std::size_t heap_end); + /** + * @brief Allocates the specified amount of memory in the heap. + * + * @param size Amount of memory to allocate. + * @return Address of the first byte to the allocated area + */ + auto allocate(std::size_t size) -> void *; + + /** + * @brief Deallocates heap memory at the specified location. + * + * @note Simply does nothing, because this allocator leaks all memory. + * + * @param pointer Pointer to the location which should be deallocated. + * @param size Size of the underlying memory area we want to deallocate. + */ + auto deallocate(uint8_t * pointer, std::size_t size) -> void; + + private: /** * @brief Returns the smallest allocatable block of heap memory. * @@ -28,6 +47,17 @@ namespace teachos::arch::memory::heap */ auto constexpr min_allocatable_size() -> std::size_t { return sizeof(memory_hole); } + /** + * @brief Splits the given hole into two, where the latter block keeps beeing free and the first part will be used + * for the allocation. + * + * @param current_hole Hole we want to split. + * @param new_hole New hole created by the split. + * + * @return Address of the hole we just split. + */ + auto split_hole(memory_hole & current_hole, memory_hole *& new_hole) -> void *; + std::size_t heap_start; ///< Start of the allocatable heap area std::size_t heap_end; ///< End of the allocatable heap area memory_hole first; ///< First free entry in our memory -- cgit v1.2.3 From 9af867de0050eef28772f7dee799666ae343950e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Thu, 28 Nov 2024 14:33:42 +0000 Subject: Start imlementation on actual algorithm --- arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp index da7fc37..5f9a72b 100644 --- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp @@ -52,15 +52,15 @@ namespace teachos::arch::memory::heap * for the allocation. * * @param current_hole Hole we want to split. - * @param new_hole New hole created by the split. + * @param size Size we want to allocate at the start of the hole. * * @return Address of the hole we just split. */ - auto split_hole(memory_hole & current_hole, memory_hole *& new_hole) -> void *; + auto split_hole(memory_hole *& current_hole, std::size_t size) -> void *; std::size_t heap_start; ///< Start of the allocatable heap area std::size_t heap_end; ///< End of the allocatable heap area - memory_hole first; ///< First free entry in our memory + memory_hole * first; ///< First free entry in our memory }; } // namespace teachos::arch::memory::heap -- cgit v1.2.3 From e8bbb1ad850a362dfa25ba1ea7bdd838a379def8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 1 Dec 2024 07:46:20 +0000 Subject: Move heap virtual location and allocate multiple variables to test heap. --- arch/x86_64/include/arch/memory/heap/concept.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/concept.hpp b/arch/x86_64/include/arch/memory/heap/concept.hpp index 8c8c887..52dba51 100644 --- a/arch/x86_64/include/arch/memory/heap/concept.hpp +++ b/arch/x86_64/include/arch/memory/heap/concept.hpp @@ -5,7 +5,7 @@ namespace teachos::arch::memory::heap { - std::size_t constexpr HEAP_START = 0x4000'0000; + std::size_t constexpr HEAP_START = 0x100000000; std::size_t constexpr HEAP_SIZE = 100 * 1024; template -- cgit v1.2.3 From eba6c94eed15b90ea8a09e4bc16ae1c0f1645dea Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 1 Dec 2024 11:08:00 +0000 Subject: implement first half of linked list dallocation --- .../include/arch/memory/heap/bump_allocator.hpp | 2 +- .../arch/memory/heap/linked_list_allocator.hpp | 12 +++++----- .../include/arch/memory/heap/memory_block.hpp | 28 ++++++++++++++++++++++ .../include/arch/memory/heap/memory_hole.hpp | 28 ---------------------- 4 files changed, 35 insertions(+), 35 deletions(-) create mode 100644 arch/x86_64/include/arch/memory/heap/memory_block.hpp delete mode 100644 arch/x86_64/include/arch/memory/heap/memory_hole.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp b/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp index 595eeea..545b72f 100644 --- a/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp @@ -42,7 +42,7 @@ namespace teachos::arch::memory::heap * @param pointer Pointer to the location which should be deallocated. * @param size Size of the underlying memory area we want to deallocate. */ - auto deallocate(uint8_t * pointer, std::size_t size) -> void; + auto deallocate(void * pointer, std::size_t size) -> void; private: std::size_t heap_start; ///< Start of the allocatable heap area diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp index 5f9a72b..99d0013 100644 --- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp @@ -1,7 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_LINKED_LIST_ALLOCATOR_HPP #define TEACHOS_ARCH_X86_64_MEMORY_HEAP_LINKED_LIST_ALLOCATOR_HPP -#include "arch/memory/heap/memory_hole.hpp" +#include "arch/memory/heap/memory_block.hpp" #include @@ -37,7 +37,7 @@ namespace teachos::arch::memory::heap * @param pointer Pointer to the location which should be deallocated. * @param size Size of the underlying memory area we want to deallocate. */ - auto deallocate(uint8_t * pointer, std::size_t size) -> void; + auto deallocate(void * pointer, std::size_t size) -> void; private: /** @@ -45,22 +45,22 @@ namespace teachos::arch::memory::heap * * @return Smallest allocatable block of heap memory. */ - auto constexpr min_allocatable_size() -> std::size_t { return sizeof(memory_hole); } + auto constexpr min_allocatable_size() -> std::size_t { return sizeof(memory_block); } /** * @brief Splits the given hole into two, where the latter block keeps beeing free and the first part will be used * for the allocation. * - * @param current_hole Hole we want to split. + * @param current_block Hole we want to split. * @param size Size we want to allocate at the start of the hole. * * @return Address of the hole we just split. */ - auto split_hole(memory_hole *& current_hole, std::size_t size) -> void *; + auto split_free_memory_block(memory_block *& current_block, std::size_t size) -> void *; std::size_t heap_start; ///< Start of the allocatable heap area std::size_t heap_end; ///< End of the allocatable heap area - memory_hole * first; ///< First free entry in our memory + memory_block * first; ///< First free entry in our memory }; } // namespace teachos::arch::memory::heap diff --git a/arch/x86_64/include/arch/memory/heap/memory_block.hpp b/arch/x86_64/include/arch/memory/heap/memory_block.hpp new file mode 100644 index 0000000..c48d0cd --- /dev/null +++ b/arch/x86_64/include/arch/memory/heap/memory_block.hpp @@ -0,0 +1,28 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_BLOCK_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_BLOCK_HPP + +#include + +namespace teachos::arch::memory::heap +{ + /** + * @brief Block containing free memory, pointing to the next free hole (nullptr) if there is none. + * Forms a single linked list. + */ + struct memory_block + { + /** + * @brief Constructor, + * + * @param size Amount of free memory of this specific hole. + * @param next Optional pointer to the next free memory. + */ + memory_block(std::size_t size, memory_block * next); + + std::size_t size; ///< Amount of free memory this hole contains, has to always be atleast 16 bytes to hold the size + ///< variable and the pointer to the next hole. + memory_block * next; ///< Optional pointer to the next free memory, holds nullptr if there is none. + }; +} // namespace teachos::arch::memory::heap + +#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_BLOCK_HPP diff --git a/arch/x86_64/include/arch/memory/heap/memory_hole.hpp b/arch/x86_64/include/arch/memory/heap/memory_hole.hpp deleted file mode 100644 index e017599..0000000 --- a/arch/x86_64/include/arch/memory/heap/memory_hole.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_HOLE_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_HOLE_HPP - -#include - -namespace teachos::arch::memory::heap -{ - /** - * @brief Block containing free memory, pointing to the next free hole (nullptr) if there is none. - * Forms a single linked list. - */ - struct memory_hole - { - /** - * @brief Constructor, - * - * @param size Amount of free memory of this specific hole. - * @param next Optional pointer to the next free memory. - */ - memory_hole(std::size_t size, memory_hole * next); - - std::size_t size; ///< Amount of free memory this hole contains, has to always be atleast 16 bytes to hold the size - ///< variable and the pointer to the next hole. - memory_hole * next; ///< Optional pointer to the next free memory, holds nullptr if there is none. - }; -} // namespace teachos::arch::memory::heap - -#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_HOLE_HPP -- cgit v1.2.3 From b8fd52b6b3a7f002cff58ff8da0313a684cb3ab4 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 1 Dec 2024 11:44:30 +0000 Subject: implement heap linked_list deallocate --- arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp index 99d0013..2d76124 100644 --- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp @@ -58,6 +58,9 @@ namespace teachos::arch::memory::heap */ auto split_free_memory_block(memory_block *& current_block, std::size_t size) -> void *; + auto coalesce_free_memory_block(memory_block *& previous_block, memory_block *& current_block, void * pointer, + std::size_t size) -> void *; + std::size_t heap_start; ///< Start of the allocatable heap area std::size_t heap_end; ///< End of the allocatable heap area memory_block * first; ///< First free entry in our memory -- cgit v1.2.3 From 2671b9522db44418536559524a22c95d3575569e Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 1 Dec 2024 12:07:42 +0000 Subject: enable heap test --- arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp index 2d76124..236d366 100644 --- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp @@ -3,8 +3,6 @@ #include "arch/memory/heap/memory_block.hpp" -#include - namespace teachos::arch::memory::heap { /** @@ -59,7 +57,7 @@ namespace teachos::arch::memory::heap auto split_free_memory_block(memory_block *& current_block, std::size_t size) -> void *; auto coalesce_free_memory_block(memory_block *& previous_block, memory_block *& current_block, void * pointer, - std::size_t size) -> void *; + std::size_t size) -> void; std::size_t heap_start; ///< Start of the allocatable heap area std::size_t heap_end; ///< End of the allocatable heap area -- cgit v1.2.3 From 9072c2a277c0da298b977cf4fb3dbebb5481abd0 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 1 Dec 2024 13:34:46 +0000 Subject: implement clear_memory_block_header --- arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp index 236d366..7432561 100644 --- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp @@ -59,6 +59,9 @@ namespace teachos::arch::memory::heap auto coalesce_free_memory_block(memory_block *& previous_block, memory_block *& current_block, void * pointer, std::size_t size) -> void; + // We cannot call delete, because it causes "undefined reference to `sbrk`". + auto clear_memory_block_header(void * pointer) -> void; + std::size_t heap_start; ///< Start of the allocatable heap area std::size_t heap_end; ///< End of the allocatable heap area memory_block * first; ///< First free entry in our memory -- cgit v1.2.3 From f880939eb5f1b5e70b15d6614cc440c09a0d9fd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 1 Dec 2024 13:57:05 +0000 Subject: Add doxygen comments for linked list helper methods. --- .../arch/memory/heap/linked_list_allocator.hpp | 41 ++++++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp index 7432561..71e495a 100644 --- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp @@ -7,7 +7,7 @@ namespace teachos::arch::memory::heap { /** * @brief Sorted by address list of memory holes (free memory). Uses free holes itself to save the information, - * containing the size and pointer to the next hole. Resulting in a single linked list. + * containing the size and pointer to the next hole. Resulting in a singly linked list. */ struct linked_list_allocator { @@ -46,20 +46,47 @@ namespace teachos::arch::memory::heap auto constexpr min_allocatable_size() -> std::size_t { return sizeof(memory_block); } /** - * @brief Splits the given hole into two, where the latter block keeps beeing free and the first part will be used - * for the allocation. + * @brief Splits the given free memory block into two, where the latter block keeps being free and the first part + * will be used for the allocation. * - * @param current_block Hole we want to split. - * @param size Size we want to allocate at the start of the hole. + * @param current_block Free memory block we want to split. + * @param size Size we want to allocate at the start of the free memory block. * - * @return Address of the hole we just split. + * @return Previous start address of the memory block we just split. */ auto split_free_memory_block(memory_block *& current_block, std::size_t size) -> void *; + /** + * @brief Combines multiple free memory blocks into one if they are adjacent. + * + * @note The internal algorithm for recombination functions like this: + * 1. Check if there is even any memory left, if not the first entry of our linked list should be a nullptr and we + * can therefore set the first entry to our newly created entry. This entry is created in the now deallocated memory + * area. + * 2. If there are more blocks but neither the previous nor the current block are adjacent, we simply create a new + * free memory block of the given size and set the previous next to our block and the next of our block to the + * current block. + * 3. If the current block is adjacent the start address of the newly created block stays the same, but the size + * increases by the amount in the current memory block header. After reading it we also clear the header. + * 4. If the previous block is adjacent the size of the previous block simply increases to include the given size as + * well. + * + * @param previous_block Free memory block before the block to deallocate in our heap memory. + * @param current_block Free memory block after the block to deallocate in our heap memory. + * @param pointer Block to deallocate. + * @param size Size of the block we want to deallocate. + */ auto coalesce_free_memory_block(memory_block *& previous_block, memory_block *& current_block, void * pointer, std::size_t size) -> void; - // We cannot call delete, because it causes "undefined reference to `sbrk`". + /** + * @brief Clears the memory of the previous memory block header. + * + * @note Done so the given pointer can be reused to construct other classes into, without having the old values. + * Required because we cannot call delete, because it causes "undefined reference to `sbrk`". + * + * @param pointer Address we want to clear the memory block header at (16 bytes) + */ auto clear_memory_block_header(void * pointer) -> void; std::size_t heap_start; ///< Start of the allocatable heap area -- cgit v1.2.3 From a5e5eabd32872f81a7190589aa648dc0e1963888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 2 Dec 2024 10:17:36 +0000 Subject: Fix algorithm issues with linked list allocator --- arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp index 71e495a..e8ecc30 100644 --- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp @@ -49,12 +49,16 @@ namespace teachos::arch::memory::heap * @brief Splits the given free memory block into two, where the latter block keeps being free and the first part * will be used for the allocation. * - * @param current_block Free memory block we want to split. + * @param previous_block Free memory block before the block to allocate in our heap memory. Was to small to allocate + * the required size into. + * @param current_block Free memory block we want to split into a size part for the allocation and the rest for + * future allocations. * @param size Size we want to allocate at the start of the free memory block. * * @return Previous start address of the memory block we just split. */ - auto split_free_memory_block(memory_block *& current_block, std::size_t size) -> void *; + auto split_free_memory_block(memory_block * previous_block, memory_block * current_block, + std::size_t size) -> void *; /** * @brief Combines multiple free memory blocks into one if they are adjacent. @@ -76,7 +80,7 @@ namespace teachos::arch::memory::heap * @param pointer Block to deallocate. * @param size Size of the block we want to deallocate. */ - auto coalesce_free_memory_block(memory_block *& previous_block, memory_block *& current_block, void * pointer, + auto coalesce_free_memory_block(memory_block * previous_block, memory_block * current_block, void * pointer, std::size_t size) -> void; /** -- cgit v1.2.3 From f7abde02150deacbc2ad1957e6165769cc2fea0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 2 Dec 2024 12:43:24 +0000 Subject: Add comment on extra double deallocation check --- arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp index e8ecc30..6af6298 100644 --- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp @@ -74,6 +74,9 @@ namespace teachos::arch::memory::heap * increases by the amount in the current memory block header. After reading it we also clear the header. * 4. If the previous block is adjacent the size of the previous block simply increases to include the given size as * well. + * 5. If the previous block is directly in our start address, so they overlap then it has to mean some or all of the + * region we are trying to deallocate has been freed before. Which would result in a double free therefore we halt + * the execution of the program. * * @param previous_block Free memory block before the block to deallocate in our heap memory. * @param current_block Free memory block after the block to deallocate in our heap memory. -- cgit v1.2.3 From dcd83b71c833e86c7e00e2b8f75ab6208b5d360d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 2 Dec 2024 13:51:58 +0000 Subject: WIP thread safe linked list --- arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp | 6 +++--- arch/x86_64/include/arch/memory/heap/memory_block.hpp | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp index 6af6298..e77602c 100644 --- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp @@ -96,9 +96,9 @@ namespace teachos::arch::memory::heap */ auto clear_memory_block_header(void * pointer) -> void; - std::size_t heap_start; ///< Start of the allocatable heap area - std::size_t heap_end; ///< End of the allocatable heap area - memory_block * first; ///< First free entry in our memory + std::size_t heap_start; ///< Start of the allocatable heap area + std::size_t heap_end; ///< End of the allocatable heap area + std::atomic first; ///< First free entry in our memory }; } // namespace teachos::arch::memory::heap diff --git a/arch/x86_64/include/arch/memory/heap/memory_block.hpp b/arch/x86_64/include/arch/memory/heap/memory_block.hpp index c48d0cd..1fbbfd5 100644 --- a/arch/x86_64/include/arch/memory/heap/memory_block.hpp +++ b/arch/x86_64/include/arch/memory/heap/memory_block.hpp @@ -1,6 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_BLOCK_HPP #define TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_BLOCK_HPP +#include #include namespace teachos::arch::memory::heap @@ -21,7 +22,7 @@ namespace teachos::arch::memory::heap std::size_t size; ///< Amount of free memory this hole contains, has to always be atleast 16 bytes to hold the size ///< variable and the pointer to the next hole. - memory_block * next; ///< Optional pointer to the next free memory, holds nullptr if there is none. + std::atomic next; ///< Optional pointer to the next free memory, holds nullptr if there is none. }; } // namespace teachos::arch::memory::heap -- cgit v1.2.3 From b4962c8c7b94fce2e67a00671de87fa96fdbb659 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 3 Dec 2024 08:00:26 +0000 Subject: add mutex to linked_list_allocator --- .../arch/memory/heap/linked_list_allocator.hpp | 8 ++-- .../include/arch/memory/heap/memory_block.hpp | 3 +- arch/x86_64/include/arch/shared/mutex.hpp | 46 ++++++++++++++++++++++ 3 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 arch/x86_64/include/arch/shared/mutex.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp index e77602c..49217d5 100644 --- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp @@ -2,6 +2,7 @@ #define TEACHOS_ARCH_X86_64_MEMORY_HEAP_LINKED_LIST_ALLOCATOR_HPP #include "arch/memory/heap/memory_block.hpp" +#include "arch/shared/mutex.hpp" namespace teachos::arch::memory::heap { @@ -96,9 +97,10 @@ namespace teachos::arch::memory::heap */ auto clear_memory_block_header(void * pointer) -> void; - std::size_t heap_start; ///< Start of the allocatable heap area - std::size_t heap_end; ///< End of the allocatable heap area - std::atomic first; ///< First free entry in our memory + std::size_t heap_start; ///< Start of the allocatable heap area + std::size_t heap_end; ///< End of the allocatable heap area + memory_block * first; ///< First free entry in our memory + shared::mutex mutex; }; } // namespace teachos::arch::memory::heap diff --git a/arch/x86_64/include/arch/memory/heap/memory_block.hpp b/arch/x86_64/include/arch/memory/heap/memory_block.hpp index 1fbbfd5..c48d0cd 100644 --- a/arch/x86_64/include/arch/memory/heap/memory_block.hpp +++ b/arch/x86_64/include/arch/memory/heap/memory_block.hpp @@ -1,7 +1,6 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_BLOCK_HPP #define TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_BLOCK_HPP -#include #include namespace teachos::arch::memory::heap @@ -22,7 +21,7 @@ namespace teachos::arch::memory::heap std::size_t size; ///< Amount of free memory this hole contains, has to always be atleast 16 bytes to hold the size ///< variable and the pointer to the next hole. - std::atomic next; ///< Optional pointer to the next free memory, holds nullptr if there is none. + memory_block * next; ///< Optional pointer to the next free memory, holds nullptr if there is none. }; } // namespace teachos::arch::memory::heap diff --git a/arch/x86_64/include/arch/shared/mutex.hpp b/arch/x86_64/include/arch/shared/mutex.hpp new file mode 100644 index 0000000..d874dd8 --- /dev/null +++ b/arch/x86_64/include/arch/shared/mutex.hpp @@ -0,0 +1,46 @@ +#ifndef TEACHOS_ARCH_X86_64_MUTEX_HPP +#define TEACHOS_ARCH_X86_64_MUTEX_HPP + +#include + +namespace teachos::arch::shared +{ + struct mutex + { + mutex() = default; + ~mutex() = default; + + mutex(const mutex &) = delete; + mutex & operator=(const mutex &) = delete; + + /** + * @brief Lock the mutex (blocks if not available) + */ + void lock() + { + while (true) + { + if (!locked.exchange(true, std::memory_order_acquire)) + { + return; + } + } + } + + /** + * @brief Try to lock the mutex (non-blocking) + * + * @return true if lock has been acquired and false otherwise + */ + bool try_lock() { return !locked.exchange(true, std::memory_order_acquire); } + + /** + * @brief Unlock the mutex + */ + void unlock() { locked.store(false, std::memory_order_release); } + + private: + std::atomic locked{false}; + }; +} // namespace teachos::arch::shared +#endif // TEACHOS_ARCH_X86_64_MUTEX_HPP \ No newline at end of file -- cgit v1.2.3 From 4f7ea612982a9ee83023e43724ff53f8dce65fe0 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 3 Dec 2024 08:06:40 +0000 Subject: improve mutex file structure --- arch/x86_64/include/arch/shared/mutex.hpp | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/shared/mutex.hpp b/arch/x86_64/include/arch/shared/mutex.hpp index d874dd8..36a4623 100644 --- a/arch/x86_64/include/arch/shared/mutex.hpp +++ b/arch/x86_64/include/arch/shared/mutex.hpp @@ -16,28 +16,19 @@ namespace teachos::arch::shared /** * @brief Lock the mutex (blocks if not available) */ - void lock() - { - while (true) - { - if (!locked.exchange(true, std::memory_order_acquire)) - { - return; - } - } - } + auto lock() -> void; /** * @brief Try to lock the mutex (non-blocking) * * @return true if lock has been acquired and false otherwise */ - bool try_lock() { return !locked.exchange(true, std::memory_order_acquire); } + auto try_lock() -> bool; /** * @brief Unlock the mutex */ - void unlock() { locked.store(false, std::memory_order_release); } + auto unlock() -> void; private: std::atomic locked{false}; -- cgit v1.2.3 From e6da0a1b12a3e777bd54e4b22b6a873a4c5fe195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 3 Dec 2024 08:19:24 +0000 Subject: Add allocate case where size fits exactly --- .../arch/memory/heap/linked_list_allocator.hpp | 40 +++++++++++++++++----- 1 file changed, 31 insertions(+), 9 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp index 49217d5..4ccc6a9 100644 --- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp @@ -23,6 +23,15 @@ namespace teachos::arch::memory::heap /** * @brief Allocates the specified amount of memory in the heap. * + * @note The specified size is used to find a free memory block with the exact same size, meaning we can remove that + * free memory block from the free list and simply return its address. Or it has to be big enough to hold the size + * and alteast enough memory for another free memory block entry (16 bytes). If the amount of memory of that free + * memory block is in between we cannot use it for our allocation, because we could only return it to the user, but + * the additional bytes, could not be used to create a free memory block. Additionaly the user couldn't know + * they received more memory than wanted. Therefore the memory would simply be unused and because it is neither + * allocated nor deallocated would never be indexed by the free memory list. We would therefore permanently loose + * that memory, to prevent that allocation into free memory blocks like that are impossible. + * * @param size Amount of memory to allocate. * @return Address of the first byte to the allocated area */ @@ -47,11 +56,24 @@ namespace teachos::arch::memory::heap auto constexpr min_allocatable_size() -> std::size_t { return sizeof(memory_block); } /** - * @brief Splits the given free memory block into two, where the latter block keeps being free and the first part - * will be used for the allocation. + * @brief Removes a free memory block from the free list and returns its address so the caller can allocate into it. + * + * @param previous_block Free memory block before the block to allocate in our heap memory. Was to small to + * allocate the required size into. + * @param current_block Free memory block we want to remove from the free list and return for the allocation. + * @param size Size we want to allocate that is exactly the same as the size of the curernt block + * + * @return Previous start address of the memory block we removed, because it has the exact required size. + */ + auto remove_free_memory_block(memory_block * previous_block, memory_block * current_block, + std::size_t size) -> void *; + + /** + * @brief Splits the given free memory block into two, where the latter block keeps being free and the first + * part will be used for the allocation. * - * @param previous_block Free memory block before the block to allocate in our heap memory. Was to small to allocate - * the required size into. + * @param previous_block Free memory block before the block to allocate in our heap memory. Was to small to + * allocate the required size into. * @param current_block Free memory block we want to split into a size part for the allocation and the rest for * future allocations. * @param size Size we want to allocate at the start of the free memory block. @@ -93,14 +115,14 @@ namespace teachos::arch::memory::heap * @note Done so the given pointer can be reused to construct other classes into, without having the old values. * Required because we cannot call delete, because it causes "undefined reference to `sbrk`". * - * @param pointer Address we want to clear the memory block header at (16 bytes) + * @param pointer Address we want to clear the memory block header at (16 bytes). */ auto clear_memory_block_header(void * pointer) -> void; - std::size_t heap_start; ///< Start of the allocatable heap area - std::size_t heap_end; ///< End of the allocatable heap area - memory_block * first; ///< First free entry in our memory - shared::mutex mutex; + std::size_t heap_start; ///< Start of the allocatable heap area. + std::size_t heap_end; ///< End of the allocatable heap area. + memory_block * first; ///< First free entry in our memory. + shared::mutex mutex; ///< Mutex to ensure only one thread calls allocate or deallocate at once. }; } // namespace teachos::arch::memory::heap -- cgit v1.2.3 From 23526b8d10cf41ad5598928bf2bf3264539d497f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 3 Dec 2024 08:41:59 +0000 Subject: Add missing comments --- .../arch/memory/heap/linked_list_allocator.hpp | 44 ++++++++++++++-------- arch/x86_64/include/arch/shared/mutex.hpp | 28 +++++++++++--- 2 files changed, 51 insertions(+), 21 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp index 4ccc6a9..5ff13ca 100644 --- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp @@ -61,12 +61,10 @@ namespace teachos::arch::memory::heap * @param previous_block Free memory block before the block to allocate in our heap memory. Was to small to * allocate the required size into. * @param current_block Free memory block we want to remove from the free list and return for the allocation. - * @param size Size we want to allocate that is exactly the same as the size of the curernt block * - * @return Previous start address of the memory block we removed, because it has the exact required size. + * @return Previous start address of the memory block we removed, because it can now be used for the allocation. */ - auto remove_free_memory_block(memory_block * previous_block, memory_block * current_block, - std::size_t size) -> void *; + auto remove_free_memory_block(memory_block * previous_block, memory_block * current_block) -> void *; /** * @brief Splits the given free memory block into two, where the latter block keeps being free and the first @@ -78,28 +76,42 @@ namespace teachos::arch::memory::heap * future allocations. * @param size Size we want to allocate at the start of the free memory block. * - * @return Previous start address of the memory block we just split. + * @return Previous start address of the memory block we just split, because it can now be used for the allocation. */ auto split_free_memory_block(memory_block * previous_block, memory_block * current_block, std::size_t size) -> void *; + /** + * @brief Removes a free memory block from the free list and returns its address so the caller can allocate into it. + * + * @param previous_block Free memory block before the block to allocate in our heap memory. Was to small to + * allocate the required size into. + * @param current_block Free memory block we want to remove from the free list and return for the allocation. + * @param new_block Replaces the current block with the given new block can be nullptr, meaning the free list will + * end here. + * + * @return Previous start address of the memory block we removed, because it can now be used for the allocation. + */ + auto replace_free_memory_block(memory_block * previous_block, memory_block * current_block, + memory_block * new_block) -> void *; + /** * @brief Combines multiple free memory blocks into one if they are adjacent. * * @note The internal algorithm for recombination functions like this: - * 1. Check if there is even any memory left, if not the first entry of our linked list should be a nullptr and we - * can therefore set the first entry to our newly created entry. This entry is created in the now deallocated memory - * area. - * 2. If there are more blocks but neither the previous nor the current block are adjacent, we simply create a new - * free memory block of the given size and set the previous next to our block and the next of our block to the - * current block. + * 1. Check if there is even any memory left, if not the first entry of our linked list should be a nullptr and + * we can therefore set the first entry to our newly created entry. This entry is created in the now deallocated + * memory area. + * 2. If there are more blocks but neither the previous nor the current block are adjacent, we simply create a + * new free memory block of the given size and set the previous next to our block and the next of our block to + * the current block. * 3. If the current block is adjacent the start address of the newly created block stays the same, but the size * increases by the amount in the current memory block header. After reading it we also clear the header. - * 4. If the previous block is adjacent the size of the previous block simply increases to include the given size as - * well. - * 5. If the previous block is directly in our start address, so they overlap then it has to mean some or all of the - * region we are trying to deallocate has been freed before. Which would result in a double free therefore we halt - * the execution of the program. + * 4. If the previous block is adjacent the size of the previous block simply increases to include the given + * size as well. + * 5. If the previous block is directly in our start address, so they overlap then it has to mean some or all of + * the region we are trying to deallocate has been freed before. Which would result in a double free therefore + * we halt the execution of the program. * * @param previous_block Free memory block before the block to deallocate in our heap memory. * @param current_block Free memory block after the block to deallocate in our heap memory. diff --git a/arch/x86_64/include/arch/shared/mutex.hpp b/arch/x86_64/include/arch/shared/mutex.hpp index 36a4623..ecd4490 100644 --- a/arch/x86_64/include/arch/shared/mutex.hpp +++ b/arch/x86_64/include/arch/shared/mutex.hpp @@ -5,33 +5,51 @@ namespace teachos::arch::shared { + /** + * @brief Custom mutex implementation, that simply wraps an atomic boolean to keep track if the mutex is already in + * use by another thread or not. + */ struct mutex { + /** + * @brief Defaulted constructor. + */ mutex() = default; + + /** + * @brief Defaulted destructor. + */ ~mutex() = default; + /** + * @brief Deleted copy constructor. + */ mutex(const mutex &) = delete; + + /** + * @brief Deleted assignment operator. + */ mutex & operator=(const mutex &) = delete; /** - * @brief Lock the mutex (blocks if not available) + * @brief Lock the mutex (blocks for as long as it is not available). */ auto lock() -> void; /** - * @brief Try to lock the mutex (non-blocking) + * @brief Try to lock the mutex (non-blocking). * - * @return true if lock has been acquired and false otherwise + * @return True if lock has been acquired and false otherwise. */ auto try_lock() -> bool; /** - * @brief Unlock the mutex + * @brief Unlock the mutex. */ auto unlock() -> void; private: - std::atomic locked{false}; + std::atomic locked = {false}; // Atomic boolean to track if mutex is locked or not. }; } // namespace teachos::arch::shared #endif // TEACHOS_ARCH_X86_64_MUTEX_HPP \ No newline at end of file -- cgit v1.2.3 From 6dff0ff5bcdd63de4a68f9c361acd0bace39b5ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 3 Dec 2024 08:52:59 +0000 Subject: Fix minor typos in mutex --- arch/x86_64/include/arch/shared/mutex.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/shared/mutex.hpp b/arch/x86_64/include/arch/shared/mutex.hpp index ecd4490..33e9e17 100644 --- a/arch/x86_64/include/arch/shared/mutex.hpp +++ b/arch/x86_64/include/arch/shared/mutex.hpp @@ -1,5 +1,5 @@ -#ifndef TEACHOS_ARCH_X86_64_MUTEX_HPP -#define TEACHOS_ARCH_X86_64_MUTEX_HPP +#ifndef TEACHOS_ARCH_X86_64_SHARED_MUTEX_HPP +#define TEACHOS_ARCH_X86_64_SHARED_MUTEX_HPP #include @@ -52,4 +52,5 @@ namespace teachos::arch::shared std::atomic locked = {false}; // Atomic boolean to track if mutex is locked or not. }; } // namespace teachos::arch::shared -#endif // TEACHOS_ARCH_X86_64_MUTEX_HPP \ No newline at end of file + +#endif // TEACHOS_ARCH_X86_64_SHARED_MUTEX_HPP -- cgit v1.2.3 From 05fe50cefb12a7333a320a3d101dccdd13b8034a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 3 Dec 2024 09:13:53 +0000 Subject: Clear old memory in contructor --- .../include/arch/memory/heap/linked_list_allocator.hpp | 10 ---------- arch/x86_64/include/arch/memory/heap/memory_block.hpp | 15 ++++++++++++--- 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp index 5ff13ca..03b8828 100644 --- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp @@ -121,16 +121,6 @@ namespace teachos::arch::memory::heap auto coalesce_free_memory_block(memory_block * previous_block, memory_block * current_block, void * pointer, std::size_t size) -> void; - /** - * @brief Clears the memory of the previous memory block header. - * - * @note Done so the given pointer can be reused to construct other classes into, without having the old values. - * Required because we cannot call delete, because it causes "undefined reference to `sbrk`". - * - * @param pointer Address we want to clear the memory block header at (16 bytes). - */ - auto clear_memory_block_header(void * pointer) -> void; - std::size_t heap_start; ///< Start of the allocatable heap area. std::size_t heap_end; ///< End of the allocatable heap area. memory_block * first; ///< First free entry in our memory. diff --git a/arch/x86_64/include/arch/memory/heap/memory_block.hpp b/arch/x86_64/include/arch/memory/heap/memory_block.hpp index c48d0cd..c62dd57 100644 --- a/arch/x86_64/include/arch/memory/heap/memory_block.hpp +++ b/arch/x86_64/include/arch/memory/heap/memory_block.hpp @@ -12,15 +12,24 @@ namespace teachos::arch::memory::heap struct memory_block { /** - * @brief Constructor, + * @brief Constructor. Clears all memory from the place it was allocated until the end (address + + * size). * * @param size Amount of free memory of this specific hole. * @param next Optional pointer to the next free memory. */ memory_block(std::size_t size, memory_block * next); - std::size_t size; ///< Amount of free memory this hole contains, has to always be atleast 16 bytes to hold the size - ///< variable and the pointer to the next hole. + /** + * @brief Destructor. Clears all internal memory. + * + * @note Used so the memory can be reused to construct other classes into, without having the old values. + * Required because we cannot call delete, because it causes "undefined reference to `sbrk`". + */ + ~memory_block(); + + std::size_t size; ///< Amount of free memory this hole contains, has to always be atleast 16 bytes to hold the + ///< size variable and the pointer to the next hole. memory_block * next; ///< Optional pointer to the next free memory, holds nullptr if there is none. }; } // namespace teachos::arch::memory::heap -- cgit v1.2.3 From 82bd19117313e6d61ab2ac03583e22b8a627f14a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 4 Dec 2024 15:32:19 +0000 Subject: Add doxygen docs file --- arch/x86_64/include/arch/boot/pointers.hpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index 1172443..29cc3cf 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -5,6 +5,9 @@ namespace teachos::arch::boot { + /** + * @brief Address pointing to the start of the multiboot information structure. + */ extern "C" size_t const multiboot_information_pointer; } // namespace teachos::arch::boot -- cgit v1.2.3 From a5c6d172b2a134f63387b0ed9055b48147f0b663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 4 Dec 2024 16:07:09 +0000 Subject: Add namespace spacing and add comment to endif --- arch/x86_64/include/arch/boot/pointers.hpp | 1 + arch/x86_64/include/arch/exception_handling/assert.hpp | 3 ++- arch/x86_64/include/arch/exception_handling/panic.hpp | 14 ++++++++++++-- arch/x86_64/include/arch/io/port_io.hpp | 2 +- arch/x86_64/include/arch/kernel/halt.hpp | 8 ++++++-- arch/x86_64/include/arch/kernel/main.hpp | 8 ++++++-- .../include/arch/memory/allocator/area_frame_allocator.hpp | 1 + arch/x86_64/include/arch/memory/allocator/concept.hpp | 1 + .../include/arch/memory/allocator/physical_frame.hpp | 1 + .../include/arch/memory/allocator/tiny_frame_allocator.hpp | 1 + arch/x86_64/include/arch/memory/cpu/control_register.hpp | 1 + arch/x86_64/include/arch/memory/cpu/msr.hpp | 1 + arch/x86_64/include/arch/memory/heap/concept.hpp | 1 + .../include/arch/memory/heap/linked_list_allocator.hpp | 1 + arch/x86_64/include/arch/memory/heap/memory_block.hpp | 1 + arch/x86_64/include/arch/memory/main.hpp | 5 +++-- .../include/arch/memory/multiboot/elf_symbols_section.hpp | 1 + arch/x86_64/include/arch/memory/multiboot/info.hpp | 1 + arch/x86_64/include/arch/memory/multiboot/memory_map.hpp | 1 + arch/x86_64/include/arch/memory/multiboot/reader.hpp | 1 + .../include/arch/memory/paging/inactive_page_table.hpp | 1 + arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 1 + arch/x86_64/include/arch/memory/paging/page_entry.hpp | 1 + arch/x86_64/include/arch/memory/paging/page_table.hpp | 1 + arch/x86_64/include/arch/memory/paging/temporary_page.hpp | 1 + arch/x86_64/include/arch/memory/paging/virtual_page.hpp | 1 + arch/x86_64/include/arch/shared/container.hpp | 1 + .../include/arch/shared/contiguous_pointer_iterator.hpp | 1 + arch/x86_64/include/arch/shared/forward_value_iterator.hpp | 1 + arch/x86_64/include/arch/shared/mutex.hpp | 1 + arch/x86_64/include/arch/video/vga/io.hpp | 2 +- arch/x86_64/include/arch/video/vga/text.hpp | 3 ++- 32 files changed, 57 insertions(+), 12 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index 29cc3cf..fe9c657 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -9,6 +9,7 @@ namespace teachos::arch::boot * @brief Address pointing to the start of the multiboot information structure. */ extern "C" size_t const multiboot_information_pointer; + } // namespace teachos::arch::boot #endif // TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP diff --git a/arch/x86_64/include/arch/exception_handling/assert.hpp b/arch/x86_64/include/arch/exception_handling/assert.hpp index 58c1f33..7dc4381 100644 --- a/arch/x86_64/include/arch/exception_handling/assert.hpp +++ b/arch/x86_64/include/arch/exception_handling/assert.hpp @@ -11,6 +11,7 @@ namespace teachos::arch::exception_handling * @param message Message that should be printed before halting the execution if the condition is not met. */ auto assert(bool condition, char const * message) -> void; + } // namespace teachos::arch::exception_handling -#endif +#endif // TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_ASSERT_HPP diff --git a/arch/x86_64/include/arch/exception_handling/panic.hpp b/arch/x86_64/include/arch/exception_handling/panic.hpp index 9566159..6a2404c 100644 --- a/arch/x86_64/include/arch/exception_handling/panic.hpp +++ b/arch/x86_64/include/arch/exception_handling/panic.hpp @@ -4,10 +4,20 @@ namespace teachos::arch::exception_handling { /** - * @brief Print a kernel panic message and then halt the system. + * @brief Print the given kernel panic message and then halt the system. + * + * @param reason Reason to print before halting the system. */ [[noreturn]] auto panic(char const * reason) -> void; + + /** + * @brief Print the given kernel panic message started by a given prefix and then halt the system. + * + * @param prefix Prefix to print before printing the reason. + * @param reason Reason to print before halting the system. + */ [[noreturn]] auto panic(char const * prefix, char const * reason) -> void; + } // namespace teachos::arch::exception_handling -#endif \ No newline at end of file +#endif // TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_PANIC_HPP diff --git a/arch/x86_64/include/arch/io/port_io.hpp b/arch/x86_64/include/arch/io/port_io.hpp index 1945261..ba41660 100644 --- a/arch/x86_64/include/arch/io/port_io.hpp +++ b/arch/x86_64/include/arch/io/port_io.hpp @@ -130,4 +130,4 @@ namespace teachos::arch::io } // namespace teachos::arch::io -#endif +#endif // TEACHOS_ARCH_X86_64_IO_PORT_IO_HPP diff --git a/arch/x86_64/include/arch/kernel/halt.hpp b/arch/x86_64/include/arch/kernel/halt.hpp index 6c58938..377acc0 100644 --- a/arch/x86_64/include/arch/kernel/halt.hpp +++ b/arch/x86_64/include/arch/kernel/halt.hpp @@ -3,7 +3,11 @@ namespace teachos::arch::kernel { + /** + * @brief Halts the kernel execution, meaning any code after a call to this will not run anymore. + */ extern "C" [[noreturn]] auto halt() -> void; -} -#endif \ No newline at end of file +} // namespace teachos::arch::kernel + +#endif // TEACHOS_ARCH_X86_64_KERNEL_HALT_HPP diff --git a/arch/x86_64/include/arch/kernel/main.hpp b/arch/x86_64/include/arch/kernel/main.hpp index 8813b46..a13e5f4 100644 --- a/arch/x86_64/include/arch/kernel/main.hpp +++ b/arch/x86_64/include/arch/kernel/main.hpp @@ -3,7 +3,11 @@ namespace teachos::arch::kernel { + /** + * @brief Initalizes the kernel system. + */ auto main() -> void; -} -#endif +} // namespace teachos::arch::kernel + +#endif // TEACHOS_ARCH_X86_64_KERNEL_MAIN_HPP 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 adba4f1..685babd 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 @@ -60,6 +60,7 @@ namespace teachos::arch::memory::allocator 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::allocator #endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP diff --git a/arch/x86_64/include/arch/memory/allocator/concept.hpp b/arch/x86_64/include/arch/memory/allocator/concept.hpp index 9d58fad..18bb6bd 100644 --- a/arch/x86_64/include/arch/memory/allocator/concept.hpp +++ b/arch/x86_64/include/arch/memory/allocator/concept.hpp @@ -17,6 +17,7 @@ namespace teachos::arch::memory::allocator { t.allocate_frame() } -> std::same_as>; { t.deallocate_frame(a) } -> std::same_as; }; + } // namespace teachos::arch::memory::allocator #endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_CONCEPT_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 index d5e2f4c..c323c10 100644 --- a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp +++ b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp @@ -80,6 +80,7 @@ namespace teachos::arch::memory::allocator }; typedef shared::container> frame_container; + } // namespace teachos::arch::memory::allocator #endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP diff --git a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp index 8124442..5a9b772 100644 --- a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp @@ -66,6 +66,7 @@ namespace teachos::arch::memory::allocator std::array, TINY_ALLOCATOR_FRAMES_COUNT> frames = {}; ///< Container that holds the frames allocated by another allocator. }; + } // namespace teachos::arch::memory::allocator #endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP diff --git a/arch/x86_64/include/arch/memory/cpu/control_register.hpp b/arch/x86_64/include/arch/memory/cpu/control_register.hpp index 4988036..9b0a4d5 100644 --- a/arch/x86_64/include/arch/memory/cpu/control_register.hpp +++ b/arch/x86_64/include/arch/memory/cpu/control_register.hpp @@ -65,6 +65,7 @@ namespace teachos::arch::memory::cpu * @param flag he flag to set in the CR2. */ auto set_cr2_bit(cr2_flags flag) -> void; + } // namespace teachos::arch::memory::cpu #endif // TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP diff --git a/arch/x86_64/include/arch/memory/cpu/msr.hpp b/arch/x86_64/include/arch/memory/cpu/msr.hpp index 49e9bcf..5cce816 100644 --- a/arch/x86_64/include/arch/memory/cpu/msr.hpp +++ b/arch/x86_64/include/arch/memory/cpu/msr.hpp @@ -58,6 +58,7 @@ namespace teachos::arch::memory::cpu * @param flag The flag to set in the EFER register. */ auto set_efer_bit(efer_flags flag) -> void; + } // namespace teachos::arch::memory::cpu #endif // TEACHOS_ARCH_X86_64_MEMORY_CPU_NXE_HPP \ No newline at end of file diff --git a/arch/x86_64/include/arch/memory/heap/concept.hpp b/arch/x86_64/include/arch/memory/heap/concept.hpp index 52dba51..1cd24f4 100644 --- a/arch/x86_64/include/arch/memory/heap/concept.hpp +++ b/arch/x86_64/include/arch/memory/heap/concept.hpp @@ -13,6 +13,7 @@ namespace teachos::arch::memory::heap { t.allocate(size) } -> std::same_as; { t.deallocate(pointer, size) } -> std::same_as; }; + } // namespace teachos::arch::memory::heap #endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_CONCEPT_HPP diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp index 03b8828..06b21bb 100644 --- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp @@ -126,6 +126,7 @@ namespace teachos::arch::memory::heap memory_block * first; ///< First free entry in our memory. shared::mutex mutex; ///< Mutex to ensure only one thread calls allocate or deallocate at once. }; + } // namespace teachos::arch::memory::heap #endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_LINKED_LIST_ALLOCATOR_HPP diff --git a/arch/x86_64/include/arch/memory/heap/memory_block.hpp b/arch/x86_64/include/arch/memory/heap/memory_block.hpp index c62dd57..502d64e 100644 --- a/arch/x86_64/include/arch/memory/heap/memory_block.hpp +++ b/arch/x86_64/include/arch/memory/heap/memory_block.hpp @@ -32,6 +32,7 @@ namespace teachos::arch::memory::heap ///< size variable and the pointer to the next hole. memory_block * next; ///< Optional pointer to the next free memory, holds nullptr if there is none. }; + } // namespace teachos::arch::memory::heap #endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_BLOCK_HPP diff --git a/arch/x86_64/include/arch/memory/main.hpp b/arch/x86_64/include/arch/memory/main.hpp index bbf160b..164abbc 100644 --- a/arch/x86_64/include/arch/memory/main.hpp +++ b/arch/x86_64/include/arch/memory/main.hpp @@ -4,12 +4,13 @@ namespace teachos::arch::memory { /** - * @brief Initializes memory management + * @brief Initializes memory management. * * @note Enables the necessary register flags and remaps the kernel, * elf_sections, vga_text and the heap. */ auto initialize_memory_management() -> void; + } // namespace teachos::arch::memory -#endif +#endif // TEACHOS_ARCH_X86_64_MEMORY_MAIN_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp index 549839a..e8f6b0a 100644 --- a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp @@ -163,6 +163,7 @@ namespace teachos::arch::memory::multiboot }; typedef shared::container> elf_section_header_container; + } // namespace teachos::arch::memory::multiboot #endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/info.hpp b/arch/x86_64/include/arch/memory/multiboot/info.hpp index 7924993..a9abf12 100644 --- a/arch/x86_64/include/arch/memory/multiboot/info.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/info.hpp @@ -58,6 +58,7 @@ namespace teachos::arch::memory::multiboot uint32_t total_size; ///< Total size of all multiboot::tags and their data. alignas(8) struct tag tags; ///< Specific tags. }; + } // namespace teachos::arch::memory::multiboot #endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_INFO_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp index 413f5a1..c28c986 100644 --- a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp @@ -47,6 +47,7 @@ namespace teachos::arch::memory::multiboot }; typedef shared::container> memory_area_container; + } // namespace teachos::arch::memory::multiboot #endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/reader.hpp b/arch/x86_64/include/arch/memory/multiboot/reader.hpp index 9707757..bda0c43 100644 --- a/arch/x86_64/include/arch/memory/multiboot/reader.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/reader.hpp @@ -47,6 +47,7 @@ namespace teachos::arch::memory::multiboot * @return Relevant data read from multiboot2. */ auto read_multiboot2() -> memory_information; + } // namespace teachos::arch::memory::multiboot #endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP diff --git a/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp b/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp index a9ab258..8d96740 100644 --- a/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp @@ -33,6 +33,7 @@ namespace teachos::arch::memory::paging allocator::physical_frame page_table_level_4_frame; ///< Temporary level 4 page table }; + } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_INACTIVE_PAGE_TABLE_HPP diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 897ae06..74f1c14 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -153,6 +153,7 @@ namespace teachos::arch::memory::paging multiboot::memory_information const & mem_info; ///< Information about elf kernel sections required for remapping process. }; + } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index a7ba262..876ea3c 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -110,6 +110,7 @@ namespace teachos::arch::memory::paging std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 9 - 11 and 52 - 62 can be ///< freely used for additional flags by the operating system. }; + } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_ENTRY_HPP diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 7a15875..51ddcd4 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -142,6 +142,7 @@ namespace teachos::arch::memory::paging level table_level; ///< Level page table is currently on, depends on how often next_level was ///< called successfully. }; + } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP diff --git a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp index 02cb545..d0d7781 100644 --- a/arch/x86_64/include/arch/memory/paging/temporary_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/temporary_page.hpp @@ -58,6 +58,7 @@ namespace teachos::arch::memory::paging virtual_page page; ///< Underlying virtual page we want to temporarily map. allocator::tiny_frame_allocator allocator; ///< Allocator that should be used to map the temporary page. }; + } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_TEMPORARY_PAGE_HPP \ No newline at end of file diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index 0ee9cbd..d820e82 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -85,6 +85,7 @@ namespace teachos::arch::memory::paging }; typedef shared::container> page_container; + } // namespace teachos::arch::memory::paging #endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP diff --git a/arch/x86_64/include/arch/shared/container.hpp b/arch/x86_64/include/arch/shared/container.hpp index b335e72..f2fd1dc 100644 --- a/arch/x86_64/include/arch/shared/container.hpp +++ b/arch/x86_64/include/arch/shared/container.hpp @@ -77,6 +77,7 @@ namespace teachos::arch::shared iterator begin_itr = {}; ///< Pointer to the first element of the given template type. iterator end_itr = {}; ///< Pointer to one pas the last element of the given template type. }; + } // namespace teachos::arch::shared #endif // TEACHOS_ARCH_X86_64_SHARED_CONTAINER_HPP diff --git a/arch/x86_64/include/arch/shared/contiguous_pointer_iterator.hpp b/arch/x86_64/include/arch/shared/contiguous_pointer_iterator.hpp index 7d5019a..e2520dc 100644 --- a/arch/x86_64/include/arch/shared/contiguous_pointer_iterator.hpp +++ b/arch/x86_64/include/arch/shared/contiguous_pointer_iterator.hpp @@ -184,6 +184,7 @@ namespace teachos::arch::shared pointer_type ptr = {}; ///< Underlying value the iterator is currently pointing too and should increment or decrement. }; + } // namespace teachos::arch::shared #endif // TEACHOS_ARCH_X86_64_SHARED_CONTIGUOUS_POINTER_ITERATOR_HPP diff --git a/arch/x86_64/include/arch/shared/forward_value_iterator.hpp b/arch/x86_64/include/arch/shared/forward_value_iterator.hpp index a84d291..c5dfc06 100644 --- a/arch/x86_64/include/arch/shared/forward_value_iterator.hpp +++ b/arch/x86_64/include/arch/shared/forward_value_iterator.hpp @@ -104,6 +104,7 @@ namespace teachos::arch::shared value_type value = {}; ///< Underlying value the iterator is currently pointing too and should increment or decrement. }; + } // namespace teachos::arch::shared #endif // TEACHOS_ARCH_X86_64_SHARED_FORWARD_VALUE_ITERATOR_HPP diff --git a/arch/x86_64/include/arch/shared/mutex.hpp b/arch/x86_64/include/arch/shared/mutex.hpp index 33e9e17..b18a8b3 100644 --- a/arch/x86_64/include/arch/shared/mutex.hpp +++ b/arch/x86_64/include/arch/shared/mutex.hpp @@ -51,6 +51,7 @@ namespace teachos::arch::shared private: std::atomic locked = {false}; // Atomic boolean to track if mutex is locked or not. }; + } // namespace teachos::arch::shared #endif // TEACHOS_ARCH_X86_64_SHARED_MUTEX_HPP diff --git a/arch/x86_64/include/arch/video/vga/io.hpp b/arch/x86_64/include/arch/video/vga/io.hpp index 3d2e90c..c399fad 100644 --- a/arch/x86_64/include/arch/video/vga/io.hpp +++ b/arch/x86_64/include/arch/video/vga/io.hpp @@ -36,4 +36,4 @@ namespace teachos::arch::video::vga } // namespace teachos::arch::video::vga -#endif +#endif // TEACHOS_ARCH_X86_64_VIDEO_VGA_IO_HPP diff --git a/arch/x86_64/include/arch/video/vga/text.hpp b/arch/x86_64/include/arch/video/vga/text.hpp index 665dc1c..cfbf98f 100644 --- a/arch/x86_64/include/arch/video/vga/text.hpp +++ b/arch/x86_64/include/arch/video/vga/text.hpp @@ -163,6 +163,7 @@ namespace teachos::arch::video::vga::text divisor /= 10; } } + } // namespace teachos::arch::video::vga::text -#endif \ No newline at end of file +#endif // TEACHOS_ARCH_X86_64_VIDEO_VGA_TEXT_HPP \ No newline at end of file -- cgit v1.2.3 From 50e2bda01928bfbad90a91439ac6326473a698b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 9 Dec 2024 12:03:39 +0000 Subject: Generate doyxgen files with build taks --- arch/x86_64/include/arch/memory/allocator/concept.hpp | 4 +--- arch/x86_64/include/arch/memory/heap/concept.hpp | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/concept.hpp b/arch/x86_64/include/arch/memory/allocator/concept.hpp index 18bb6bd..2d3f4ae 100644 --- a/arch/x86_64/include/arch/memory/allocator/concept.hpp +++ b/arch/x86_64/include/arch/memory/allocator/concept.hpp @@ -8,9 +8,7 @@ namespace teachos::arch::memory::allocator { /** - * @brief Frame allocator concept - * - * @tparam T + * @brief Frame allocator concept required for allocating and deallocating physical frames in memory. */ template concept FrameAllocator = requires(T t, physical_frame const & a) { diff --git a/arch/x86_64/include/arch/memory/heap/concept.hpp b/arch/x86_64/include/arch/memory/heap/concept.hpp index 1cd24f4..e22e35f 100644 --- a/arch/x86_64/include/arch/memory/heap/concept.hpp +++ b/arch/x86_64/include/arch/memory/heap/concept.hpp @@ -8,6 +8,9 @@ namespace teachos::arch::memory::heap std::size_t constexpr HEAP_START = 0x100000000; std::size_t constexpr HEAP_SIZE = 100 * 1024; + /** + * @brief Heap allocator concept required for allocating and managing free space on the heap. + */ template concept HeapAllocator = requires(T t, uint8_t * pointer, std::size_t size) { { t.allocate(size) } -> std::same_as; -- cgit v1.2.3 From 4ff0477e844fe13620b02c197a8db4c01809399f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 9 Dec 2024 15:16:50 +0000 Subject: Fix method writing to wrong CR register and improve doxygen comments. --- .../include/arch/exception_handling/assert.hpp | 2 +- .../arch/memory/allocator/area_frame_allocator.hpp | 5 ++-- .../arch/memory/allocator/physical_frame.hpp | 2 +- .../arch/memory/allocator/tiny_frame_allocator.hpp | 4 +++- .../include/arch/memory/cpu/control_register.hpp | 16 ++++++------- arch/x86_64/include/arch/memory/cpu/msr.hpp | 28 +++++++++++----------- arch/x86_64/include/arch/memory/cpu/tlb.hpp | 5 +++- .../include/arch/memory/heap/memory_block.hpp | 2 +- 8 files changed, 35 insertions(+), 29 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/exception_handling/assert.hpp b/arch/x86_64/include/arch/exception_handling/assert.hpp index 7dc4381..1286768 100644 --- a/arch/x86_64/include/arch/exception_handling/assert.hpp +++ b/arch/x86_64/include/arch/exception_handling/assert.hpp @@ -5,7 +5,7 @@ namespace teachos::arch::exception_handling { /** * @brief Assert a condition to be true, if not do not continue - * execution of the code and print the formatted message to screen. + * execution of the code and print the given message to screen. * * @param condition Condition we want to be true or else halt execution. * @param message Message that should be printed before halting the execution if the condition is not met. 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 685babd..b8370db 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 @@ -9,7 +9,8 @@ namespace teachos::arch::memory::allocator { /** - * @brief Allocates memory using memory areas read from the multiboot2 information pointer. + * @brief Allocates memory linearly using memory areas read from the multiboot2 information pointer and leaks any + * deallocated frames. */ struct area_frame_allocator { @@ -39,7 +40,7 @@ namespace teachos::arch::memory::allocator * * @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 ben alocated in the first place. + * does not know which frames have been alocated in the first place. * * @param physical_frame Previously allocated physical_frame that should be deallocated. */ diff --git a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp index c323c10..7f04042 100644 --- a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp +++ b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp @@ -45,7 +45,7 @@ namespace teachos::arch::memory::allocator auto static containing_address(physical_address address) -> physical_frame; /** - * @brief Evaluates the start address of the physical frame. + * @brief Get the start address of this physical frame. * * @return Start address of the physical frame. */ diff --git a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp index 5a9b772..1ceb74d 100644 --- a/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/allocator/tiny_frame_allocator.hpp @@ -14,7 +14,9 @@ namespace teachos::arch::memory::allocator } /** - * @brief Allocates memory using memory areas read from the multiboot2 information pointer. + * @brief Allocates memory using memory areas read from the multiboot2 information pointer. Does not allocate its own + * frames, but uses the necessary three frames provided by another allocator to map one virtual level 1 page entry and + * the necessary upper layers. */ struct tiny_frame_allocator { diff --git a/arch/x86_64/include/arch/memory/cpu/control_register.hpp b/arch/x86_64/include/arch/memory/cpu/control_register.hpp index 9b0a4d5..e11813d 100644 --- a/arch/x86_64/include/arch/memory/cpu/control_register.hpp +++ b/arch/x86_64/include/arch/memory/cpu/control_register.hpp @@ -27,14 +27,14 @@ namespace teachos::arch::memory::cpu }; /** - * @brief Control register 2 flags that can be set. + * @brief Control register 0 flags that can be set. * * @note Modifies the basic operation of the processor. Only the most important extensions are listed below, the rest * are excluded for brevity. See https://en.wikipedia.org/wiki/Control_register#CR0 for more information. */ - enum struct cr2_flags : uint64_t + enum struct cr0_flags : uint64_t { - PROTECTED_MODE_ENABLED = 1U << 0U, ///< System is in protected moe else system is in real mode. + PROTECTED_MODE_ENABLED = 1U << 0U, ///< System is in protected or system is in real mode. TASK_SWITCHED = 1U << 3U, ///< Allows saving x87 task context upon a task switch only after x87 instruction used. WRITE_PROTECT = 1U << 16U, ///< When set, the CPU cannot write to read-only pages when privilege level is 0. PAGING = 1U << 31U, // Enable paging using the CR3 register. @@ -57,14 +57,14 @@ namespace teachos::arch::memory::cpu auto write_control_register(control_register cr, uint64_t new_value) -> void; /** - * @brief Sets a specific bit in the CR2. + * @brief Sets a specific bit in the CR0. * - * @note This function reads the current value of the CR2 register, ORs the specified - * bit with the current value, and writes the updated value back to the CR2. + * @note This function reads the current value of the CR0 register, ORs the specified + * bit with the current value, and writes the updated value back to the CR0. * - * @param flag he flag to set in the CR2. + * @param flag he flag to set in the CR0. */ - auto set_cr2_bit(cr2_flags flag) -> void; + auto set_cr0_bit(cr0_flags flag) -> void; } // namespace teachos::arch::memory::cpu diff --git a/arch/x86_64/include/arch/memory/cpu/msr.hpp b/arch/x86_64/include/arch/memory/cpu/msr.hpp index 5cce816..cda70e2 100644 --- a/arch/x86_64/include/arch/memory/cpu/msr.hpp +++ b/arch/x86_64/include/arch/memory/cpu/msr.hpp @@ -7,7 +7,7 @@ namespace teachos::arch::memory::cpu { /** - * @brief Important Flags that can be writen into the Extended Feature Enable Register (EFER). + * @brief Important flags that can be writen into the Extended Feature Enable Register (EFER). * * @note EFER is a model-specific register allowing to configure CPU extensions. Only the most important extensions * are listed below, the rest are excluded for brevity. See https://en.wikipedia.org/wiki/Control_register#EFER for @@ -15,22 +15,21 @@ namespace teachos::arch::memory::cpu */ enum class efer_flags : uint64_t { - SCE = 1UL << 0UL, ///< System Call Extensions - LME = 1UL << 8UL, ///< Long Mode Enabled - LMA = 1UL << 10UL, ///< Long Mode Active - NXE = 1UL << 11UL, ///< No-Execute Enable - SVME = 1UL << 12UL, ///< Secure Virtual Machine Enable - LMSLE = 1UL << 13UL, ///< Long Mode Segment Limit Enable - FFXSR = 1UL << 14UL, ///< Fast FXSAVE/FXSTOR - TCE = 1UL << 15UL, ///< Translation Cache Extension + SCE = 1UL << 0UL, ///< System Call Extensions. + LME = 1UL << 8UL, ///< Long Mode Enabled. + LMA = 1UL << 10UL, ///< Long Mode Active. + NXE = 1UL << 11UL, ///< No-Execute Enable. + SVME = 1UL << 12UL, ///< Secure Virtual Machine Enable. + LMSLE = 1UL << 13UL, ///< Long Mode Segment Limit Enable. + FFXSR = 1UL << 14UL, ///< Fast FXSAVE/FXSTOR. + TCE = 1UL << 15UL, ///< Translation Cache Extension. }; /** - * @brief Reads a 64-bit Model-Specific Register (MSR). + * @brief Reads a 64-bit from the Model-Specific Register (MSR). * - * @note This function reads the value of an MSR specified by the given address. It - * combines the lower and upper 32-bits of the MSR value and returns it as a - * 64-bit unsigned integer. + * @note This function reads the value of an MSR specified by the given address. It combines the lower and upper + * 32-bits of the MSR value read using the 'rdmsr' instruction and returns it as a 64-bit unsigned integer. * * @param msr The address of the MSR to read. * @return The 64-bit value read from the MSR. @@ -50,7 +49,8 @@ namespace teachos::arch::memory::cpu auto write_msr(uint32_t msr, uint64_t new_value) -> void; /** - * @brief Sets a specific bit in the Extended Feature Enable Register (EFER) Model-Specific Register (MSR) register. + * @brief Sets a specific bit in the Extended Feature Enable Register (EFER), which is a Model-Specific Register + * (MSR). * * @note This function reads the current value of the EFER register, ORs the specified * bit with the current value, and writes the updated value back to the EFER register. diff --git a/arch/x86_64/include/arch/memory/cpu/tlb.hpp b/arch/x86_64/include/arch/memory/cpu/tlb.hpp index 21f09e5..075d7bb 100644 --- a/arch/x86_64/include/arch/memory/cpu/tlb.hpp +++ b/arch/x86_64/include/arch/memory/cpu/tlb.hpp @@ -15,7 +15,10 @@ namespace teachos::arch::memory::cpu auto tlb_flush(paging::virtual_address address) -> void; /** - * @brief Invalidates the translation lookaside buffer (TLB) entry for all page tables + * @brief Invalidates the translation lookaside buffer (TLB) entry for all page tables. + * + * @note Simply reassigns the CR3 register the value of the CR3 register, causing a flush of the TLB buffer, because + * the system has to assume that the location of the level 4 page table moved. */ auto tlb_flush_all() -> void; diff --git a/arch/x86_64/include/arch/memory/heap/memory_block.hpp b/arch/x86_64/include/arch/memory/heap/memory_block.hpp index 502d64e..b9a2254 100644 --- a/arch/x86_64/include/arch/memory/heap/memory_block.hpp +++ b/arch/x86_64/include/arch/memory/heap/memory_block.hpp @@ -7,7 +7,7 @@ namespace teachos::arch::memory::heap { /** * @brief Block containing free memory, pointing to the next free hole (nullptr) if there is none. - * Forms a single linked list. + * Forms a singly linked list of free memory blocks that we can callocate memory into. */ struct memory_block { -- cgit v1.2.3 From 3d488e53a1d15fcc01a7b1d23b9585ca7a724864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 17 Dec 2024 09:36:31 +0000 Subject: Fix typo --- arch/x86_64/include/arch/memory/paging/page_table.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 51ddcd4..60a0a2f 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -140,7 +140,7 @@ namespace teachos::arch::memory::paging page_table * table; ///< Handle to underlying page table, can never be null (invariant ensured by ///< constructor) level table_level; ///< Level page table is currently on, depends on how often next_level was - ///< called successfully. + ///< called successfuly. }; } // namespace teachos::arch::memory::paging -- cgit v1.2.3