]> git.ameliathe1st.gay Git - voyage-au-centre-des-fichiers.git/commitdiff
Made page a template, to support all the different page sizes
authorAmelia Coutard <eliottulio.coutard@gmail.com>
Tue, 5 Dec 2023 14:57:31 +0000 (15:57 +0100)
committerAmelia Coutard <eliottulio.coutard@gmail.com>
Tue, 5 Dec 2023 14:57:31 +0000 (15:57 +0100)
kernel/src/kernel.cpp
kernel/src/paging.cpp
kernel/src/paging.hpp

index 82ac43fe5d266de142fdf2d19690160758ff2dff..beddfac353403298519bb3d52cebd3b4b3492fee 100644 (file)
@@ -24,7 +24,7 @@ extern "C" os::tss TSS;
 extern "C" char interrupt_stack_top;
 extern "C" os::paging::PML4T PML4T;
 
-os::paging::page bootstrap_pages_for_memory[32]; // 32 pages = 128 KiB
+os::paging::page<0> bootstrap_pages_for_memory[32]; // 32 pages = 128 KiB
 
 extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_start> info) {
        os::assert(magic == 0x36D76289, "Incorrect magic number: wasn't booted with multiboot2.");
@@ -37,7 +37,7 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
        }
 
        os::paging::page_allocator.deallocate({
-               .ptr = os::phys_ptr<os::paging::page>(reinterpret_cast<uintptr_t>(bootstrap_pages_for_memory) - 0xFFFF'FFFF'8000'0000),
+               .ptr = os::phys_ptr<os::paging::page<0>>(reinterpret_cast<uintptr_t>(bootstrap_pages_for_memory) - 0xFFFF'FFFF'8000'0000),
                .size = sizeof(bootstrap_pages_for_memory) / sizeof(bootstrap_pages_for_memory[0])
        });
 
@@ -94,8 +94,8 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 
        {
                struct {
-                       os::phys_ptr<os::paging::page> start_address = nullptr;
-                       os::phys_ptr<os::paging::page> end_address = nullptr;
+                       os::phys_ptr<os::paging::page<0>> start_address = nullptr;
+                       os::phys_ptr<os::paging::page<0>> end_address = nullptr;
                } available_ram[50];
                std::size_t available_ram_length = 0;
 
@@ -112,10 +112,10 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
                                for (std::size_t i = 0; i < multiboot2::memory_map_number_of_entries(it); i++) {
                                        if (multiboot2::memory_map_type(it, i) == 1) {
                                                // Rounded up, to avoid including non-ram.
-                                               const os::phys_ptr<os::paging::page>
+                                               const os::phys_ptr<os::paging::page<0>>
                                                        s{(multiboot2::memory_map_base_addr(it, i) + 0x1000 - 1) / 0x1000 * 0x1000};
                                                // Rounded down, to avoid including non-ram.
-                                               const os::phys_ptr<os::paging::page>
+                                               const os::phys_ptr<os::paging::page<0>>
                                                        e{(multiboot2::memory_map_base_addr(it, i) + multiboot2::memory_map_length(it, i)) / 0x1000 * 0x1000 - 0x1000};
                                                if (s <= e) { // In the case where no full page is included in the ram section, don't add it.
                                                        os::assert(available_ram_length < 50, "Too much available RAM sections to initialise correctly. Will fix eventually, probably.");
@@ -139,13 +139,13 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
                os::assert(module_specified, "No modules specified in the multiboot. This is unsupported.");
 
                // kernel_start and kernel_end are aligned to 4K by the linker script.
-               const os::phys_ptr<os::paging::page> kernel_s = ([]() {
-                       os::phys_ptr<os::paging::page> ptr = nullptr;
+               const os::phys_ptr<os::paging::page<0>> kernel_s = ([]() {
+                       os::phys_ptr<os::paging::page<0>> ptr = nullptr;
                        asm("mov $_kernel_phys_start,%0" : "=ri"(ptr));
                        return ptr;
                })();
-               const os::phys_ptr<os::paging::page> kernel_e = ([]() {
-                       os::phys_ptr<os::paging::page> ptr = nullptr;
+               const os::phys_ptr<os::paging::page<0>> kernel_e = ([]() {
+                       os::phys_ptr<os::paging::page<0>> ptr = nullptr;
                        asm("mov $_kernel_phys_end,%0" : "=ri"(ptr));
                        return ptr - 1; // [s, e], not [s, e[
                })();
@@ -186,7 +186,7 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 
        // Unmap low RAM, and free corresponding page.
        PML4T.contents[0].non_page.P = false;
-       os::paging::page_allocator.deallocate({.ptr = os::phys_ptr<os::paging::page>(get_base_address(PML4T.contents[0]).get_phys_addr()), .size = 1});
+       os::paging::page_allocator.deallocate({.ptr = os::phys_ptr<os::paging::page<0>>(get_base_address(PML4T.contents[0]).get_phys_addr()), .size = 1});
        os::invlpg((void*)0x0);
 
        os::print("Loading ring 3 interrupts stack.\n");
index 8fec68d3fffdc3ce8909cb767bea7f187b175d4e..532b3062cf80daee499957224ed322db2b3a75ad 100644 (file)
@@ -48,42 +48,44 @@ std::byte* os::paging::setup_page(os::paging::PML4T& PML4T, const void* vaddr, b
                {.page = {.P = 1, .R_W = R_W, .U_S = U_S, .PWT = 0, .PCD = 0, .PAT = 0, .G = (indices.pml4e < 128) ? 0ul : 1ul, .base_address = 0, .NX = 0}};
        const auto page_alloc = os::paging::page_allocator.allocate(1);
        memset((void*)page_alloc.ptr, 0, 0x1000);
-       set_page_base_address(PT.contents[indices.pe], os::phys_ptr<os::paging::page>(page_alloc.ptr.get_phys_addr()));
+       set_page_base_address(PT.contents[indices.pe], os::phys_ptr<os::paging::page<0>>(page_alloc.ptr.get_phys_addr()));
        invlpg(vaddr);
        return (std::byte*)&*page_alloc.ptr;
 }
 
 namespace {
-void on_all_pages(const os::paging::PT& PT, void f(os::paging::page*, os::phys_ptr<os::paging::page>, std::size_t), std::size_t PT_virt_address) {
+void on_all_pages(const os::paging::PT& PT, void f(os::paging::page<0>*, os::phys_ptr<os::paging::page<0>>, std::size_t), std::size_t PT_virt_address) {
        for (std::size_t i = 0; i < 512; i++) {
                if (!PT.contents[i].page.P) {
                        continue;
                }
                std::uint64_t virt_address = PT_virt_address | (i * 0x1000ull);
-               f(reinterpret_cast<os::paging::page*>(virt_address), os::paging::get_page_base_address(PT.contents[i]), 0x1000ull);
+               f(reinterpret_cast<os::paging::page<0>*>(virt_address), os::paging::get_page_base_address(PT.contents[i]), 0x1000ull);
        }
 }
-void on_all_pages(const os::paging::PDT& PDT, void f(os::paging::page*, os::phys_ptr<os::paging::page>, std::size_t), std::size_t PDT_virt_address) {
+void on_all_pages(const os::paging::PDT& PDT, void f(os::paging::page<0>*, os::phys_ptr<os::paging::page<0>>, std::size_t), std::size_t PDT_virt_address) {
        for (std::size_t i = 0; i < 512; i++) {
                if (!PDT.contents[i].page.P) {
                        continue;
                }
                std::uint64_t virt_address = PDT_virt_address | (i * 0x1000ull * 512ull);
                if (os::paging::is_page(PDT.contents[i])) {
-                       f(reinterpret_cast<os::paging::page*>(virt_address), os::paging::get_page_base_address(PDT.contents[i]), 0x1000ull * 512ull);
+                       f(reinterpret_cast<os::paging::page<0>*>(virt_address),
+                               os::phys_ptr<os::paging::page<0>>(os::paging::get_page_base_address(PDT.contents[i]).get_phys_addr()), 0x1000ull * 512ull);
                } else {
                        on_all_pages(*os::paging::get_base_address(PDT.contents[i]), f, virt_address);
                }
        }
 }
-void on_all_pages(const os::paging::PDPT& PDPT, void f(os::paging::page*, os::phys_ptr<os::paging::page>, std::size_t), std::size_t PDPT_virt_address) {
+void on_all_pages(const os::paging::PDPT& PDPT, void f(os::paging::page<0>*, os::phys_ptr<os::paging::page<0>>, std::size_t), std::size_t PDPT_virt_address) {
        for (std::size_t i = 0; i < 512; i++) {
                if (!PDPT.contents[i].page.P) {
                        continue;
                }
                std::uint64_t virt_address = PDPT_virt_address | (i * 0x1000ull * 512ull * 512ull);
                if (os::paging::is_page(PDPT.contents[i])) {
-                       f(reinterpret_cast<os::paging::page*>(virt_address), os::paging::get_page_base_address(PDPT.contents[i]), 0x1000ull * 512ull * 512ull);
+                       f(reinterpret_cast<os::paging::page<0>*>(virt_address),
+                               os::phys_ptr<os::paging::page<0>>(os::paging::get_page_base_address(PDPT.contents[i]).get_phys_addr()), 0x1000ull * 512ull * 512ull);
                } else {
                        on_all_pages(*os::paging::get_base_address(PDPT.contents[i]), f, virt_address);
                }
@@ -92,7 +94,7 @@ void on_all_pages(const os::paging::PDPT& PDPT, void f(os::paging::page*, os::ph
 
 } // namespace
 
-void os::paging::on_all_pages(const os::paging::PML4T& PML4T, void f(page*, phys_ptr<page>, std::size_t)) {
+void os::paging::on_all_pages(const os::paging::PML4T& PML4T, void f(page<0>*, phys_ptr<page<0>>, std::size_t)) {
        for (std::size_t i = 0; i < 512; i++) {
                if (!PML4T.contents[i].non_page.P) {
                        continue;
@@ -121,7 +123,7 @@ os::paging::page_allocator_t::block os::paging::page_allocator_t::allocate(std::
                return { .ptr = nullptr, .size = count };
        }
        if (begin->size == count) {
-               block result = { .ptr = phys_ptr<paging::page>{begin.get_phys_addr()}, .size = count };
+               block result = { .ptr = phys_ptr<paging::page<0>>{begin.get_phys_addr()}, .size = count };
                begin = begin->next;
                return result;
        }
@@ -129,11 +131,11 @@ os::paging::page_allocator_t::block os::paging::page_allocator_t::allocate(std::
        for (phys_ptr<page> it = begin; it != nullptr; it = it->next) {
                if (it->size == count) {
                        prec->next = it->next;
-                       return { .ptr = phys_ptr<paging::page>{it.get_phys_addr()}, .size = count };
+                       return { .ptr = phys_ptr<paging::page<0>>{it.get_phys_addr()}, .size = count };
                }
                if (it->size > count) {
                        it->size -= count;
-                       return { .ptr = phys_ptr<paging::page>{it.get_phys_addr()} + it->size, .size = count };
+                       return { .ptr = phys_ptr<paging::page<0>>{it.get_phys_addr()} + it->size, .size = count };
                }
                prec = it;
        }
index 41ac1bec71274426cafed9e1fcfb62670ee2bb21..d4ed443513200981e983a6d32d8c46a9bf9ed1b5 100644 (file)
@@ -24,23 +24,24 @@ template <std::size_t depth> struct paging_entry;
 template <std::size_t depth> struct __attribute__((aligned(0x1000))) paging_table {
        paging_entry<depth> contents[512];
 };
-template <> struct __attribute__((aligned(0x1000))) paging_table<0> {
-       std::byte contents[4096];
-};
-static_assert(sizeof(paging_table<0>) == 0x1000);
-static_assert(alignof(paging_table<0>) == 0x1000);
 
-using PML4T = paging_table<4>;
-using PML4E = paging_entry<4>;
-using PDPT = paging_table<3>;
-using PDPE = paging_entry<3>;
-using PDT = paging_table<2>;
-using PDE = paging_entry<2>;
-using PT = paging_table<1>;
-using PE = paging_entry<1>;
-using page = paging_table<0>;
+using PML4T = paging_table<3>;
+using PML4E = paging_entry<3>;
+using PDPT = paging_table<2>;
+using PDPE = paging_entry<2>;
+using PDT = paging_table<1>;
+using PDE = paging_entry<1>;
+using PT = paging_table<0>;
+using PE = paging_entry<0>;
+// Alignment should be the same as size, but that's literally too big for the compiler.
+template <std::size_t depth> struct __attribute__((aligned(0x1000))) page {
+       std::byte contents[0x1000ull << (9 * depth)];
+};
+static_assert(sizeof(page<0>) == 0x1000);
+static_assert(sizeof(page<1>) == 0x1000 * 512);
+static_assert(sizeof(page<2>) == 0x1000ull * 512 * 512);
 
-template<> struct paging_entry<4> {
+template<> struct paging_entry<3> {
        struct {
                std::uint64_t P : 1 = 0;
                std::uint64_t R_W : 1;
@@ -56,12 +57,12 @@ template<> struct paging_entry<4> {
                std::uint64_t NX : 1;
        } non_page;
 };
-static_assert(sizeof(paging_table<4>) == 0x1000);
-static_assert(alignof(paging_table<4>) == 0x1000);
-static_assert(alignof(paging_entry<4>) == 8);
-static_assert(sizeof(paging_entry<4>) == 8);
+static_assert(sizeof(paging_table<3>) == 0x1000);
+static_assert(alignof(paging_table<3>) == 0x1000);
+static_assert(alignof(paging_entry<3>) == 8);
+static_assert(sizeof(paging_entry<3>) == 8);
 
-template<> struct paging_entry<3> {
+template<> struct paging_entry<2> {
 union {
        struct {
                std::uint64_t P : 1 = 0;
@@ -98,12 +99,12 @@ union {
        } page;
 };
 };
-static_assert(sizeof(paging_table<3>) == 0x1000);
-static_assert(alignof(paging_table<3>) == 0x1000);
-static_assert(alignof(paging_entry<3>) == 8);
-static_assert(sizeof(paging_entry<3>) == 8);
+static_assert(sizeof(paging_table<2>) == 0x1000);
+static_assert(alignof(paging_table<2>) == 0x1000);
+static_assert(alignof(paging_entry<2>) == 8);
+static_assert(sizeof(paging_entry<2>) == 8);
 
-template <> struct paging_entry<2> {
+template <> struct paging_entry<1> {
 union {
        struct {
                std::uint64_t P : 1 = 0;
@@ -140,12 +141,12 @@ union {
        } page;
 };
 };
-static_assert(sizeof(paging_table<2>) == 0x1000);
-static_assert(alignof(paging_table<2>) == 0x1000);
-static_assert(alignof(paging_entry<2>) == 8);
-static_assert(sizeof(paging_entry<2>) == 8);
+static_assert(sizeof(paging_table<1>) == 0x1000);
+static_assert(alignof(paging_table<1>) == 0x1000);
+static_assert(alignof(paging_entry<1>) == 8);
+static_assert(sizeof(paging_entry<1>) == 8);
 
-template <> struct paging_entry<1> {
+template <> struct paging_entry<0> {
        struct {
                std::uint64_t P : 1 = 0;
                std::uint64_t R_W : 1;
@@ -163,10 +164,10 @@ template <> struct paging_entry<1> {
                std::uint64_t NX : 1;
        } page;
 };
-static_assert(sizeof(paging_table<1>) == 0x1000);
-static_assert(alignof(paging_table<1>) == 0x1000);
-static_assert(alignof(paging_entry<1>) == 8);
-static_assert(sizeof(paging_entry<1>) == 8);
+static_assert(sizeof(paging_table<0>) == 0x1000);
+static_assert(alignof(paging_table<0>) == 0x1000);
+static_assert(alignof(paging_entry<0>) == 8);
+static_assert(sizeof(paging_entry<0>) == 8);
 
 
 inline bool is_page(const PML4E __attribute__((unused))& PML4E) { return false; }
@@ -186,17 +187,17 @@ inline phys_ptr<PT> get_base_address(const PDE& PDE) {
        os::assert(!is_page(PDE), "Tried to get non-page out of a page paging.");
        return phys_ptr<PT>{PDE.non_page.base_address * 0x1000ull};
 }
-inline phys_ptr<page> get_page_base_address(const PDPE& PDPE) {
+inline phys_ptr<page<2>> get_page_base_address(const PDPE& PDPE) {
        os::assert(is_page(PDPE), "Tried to get page out of a non-page paging.");
-       return phys_ptr<page>{PDPE.page.base_address * 0x1000ull * 512ull * 512ull};
+       return phys_ptr<page<2>>{PDPE.page.base_address * sizeof(page<2>)};
 }
-inline phys_ptr<page> get_page_base_address(const PDE& PDE) {
+inline phys_ptr<page<1>> get_page_base_address(const PDE& PDE) {
        os::assert(is_page(PDE), "Tried to get page out of a non-page paging.");
-       return phys_ptr<page>{PDE.page.base_address * 0x1000ull * 512ull};
+       return phys_ptr<page<1>>{PDE.page.base_address * sizeof(page<1>)};
 }
-inline phys_ptr<page> get_page_base_address(const PE& PE) {
+inline phys_ptr<page<0>> get_page_base_address(const PE& PE) {
        os::assert(is_page(PE), "Tried to get page out of a non-page paging.");
-       return phys_ptr<page>{PE.page.base_address * 0x1000ull};
+       return phys_ptr<page<0>>{PE.page.base_address * sizeof(page<0>)};
 }
 
 inline void set_base_address(PML4E& PML4E, phys_ptr<PDPT> ptr) {
@@ -211,17 +212,17 @@ inline void set_base_address(PDE& PDE, phys_ptr<PT> ptr) {
        os::assert(!is_page(PDE), "Tried to get non-page out of a page paging.");
        PDE.non_page.base_address = ptr.get_phys_addr() / 0x1000ull;
 }
-inline void set_page_base_address(PDPE& PDPE, phys_ptr<page> ptr) {
+inline void set_page_base_address(PDPE& PDPE, phys_ptr<page<2>> ptr) {
        os::assert(is_page(PDPE), "Tried to get page out of a non-page paging.");
-       PDPE.page.base_address = ptr.get_phys_addr() / 0x1000ull / 512ull / 512ull;
+       PDPE.page.base_address = ptr.get_phys_addr() / sizeof(*ptr);
 }
-inline void set_page_base_address(PDE& PDE, phys_ptr<page> ptr) {
+inline void set_page_base_address(PDE& PDE, phys_ptr<page<1>> ptr) {
        os::assert(is_page(PDE), "Tried to get page out of a non-page paging.");
-       PDE.page.base_address = ptr.get_phys_addr() / 0x1000ull / 512ull;
+       PDE.page.base_address = ptr.get_phys_addr() / sizeof(*ptr);
 }
-inline void set_page_base_address(PE& PE, phys_ptr<page> ptr) {
+inline void set_page_base_address(PE& PE, phys_ptr<page<0>> ptr) {
        os::assert(is_page(PE), "Tried to get page out of a non-page paging.");
-       PE.page.base_address = ptr.get_phys_addr() / 0x1000ull;
+       PE.page.base_address = ptr.get_phys_addr() / sizeof(*ptr);
 }
 
 struct page_table_indices {
@@ -242,7 +243,7 @@ constexpr page_table_indices calc_page_table_indices(const void* ptr) {
 std::byte* setup_page(PML4T& PML4T, const void* vaddr, bool R_W, bool U_S);
 
 // For all present page mappings, calls f(virtual address, physical address, page size in bytes (4KiB, 2MiB or 1GiB)).
-void on_all_pages(const PML4T& PML4T, void f(page*, phys_ptr<page>, std::size_t));
+void on_all_pages(const PML4T& PML4T, void f(page<0>*, phys_ptr<page<0>>, std::size_t));
 
 void load_pml4t(phys_ptr<PML4T> PML4T);
 
@@ -252,7 +253,7 @@ extern page_allocator_t page_allocator;
 class page_allocator_t {
 public:
        struct block {
-               phys_ptr<paging::page> ptr = nullptr;
+               phys_ptr<paging::page<0>> ptr = nullptr;
                std::uint64_t size;
        };