]> git.ameliathe1st.gay Git - voyage-au-centre-des-fichiers.git/commitdiff
Changed the page tables to use bitfields
authorAmelia Coutard <eliottulio.coutard@gmail.com>
Thu, 13 Oct 2022 09:26:43 +0000 (11:26 +0200)
committerAmelia Coutard <eliottulio.coutard@gmail.com>
Thu, 13 Oct 2022 14:44:57 +0000 (16:44 +0200)
src/kernel.cpp
src/paging.cpp
src/paging.hpp

index 850c108e5dfa829abab07396a5eb1bd650f2cc2a..76d516738c96104ac369188a4393109e0f68bc29 100644 (file)
@@ -133,17 +133,15 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
                os::enable_interrupts(isr_info, idt);
        }
 
-       PML4T.contents[0].base_address()->contents[0].P(false);
-       PML4T.contents[0].base_address()->contents[1].P(false);
-       PML4T.contents[0].P(false);
-       os::print("Mapping:\n");
-       os::paging::print_mapping(PML4T);
+       get_base_address(PML4T.contents[0])->contents[0].page.P = false;
+       get_base_address(PML4T.contents[0])->contents[1].page.P = false;
+       PML4T.contents[0].P = false;
 
        // Allow userspaaaaaaaaace in ring 3. Otherwise, we just immediately page fault.
        // Will make it a module soon-ish.
-       PML4T.contents[511].base_address()->contents[510].U_S(true);
-       PML4T.contents[511].base_address()->contents[511].U_S(true);
-       PML4T.contents[511].U_S(true);
+       get_base_address(PML4T.contents[511])->contents[510].page.U_S = true;
+       get_base_address(PML4T.contents[511])->contents[511].page.U_S = true;
+       PML4T.contents[511].U_S = true;
 
        os::print("Load ring 3 interrupts stack:\n");
        os::set_ring0_stack(TSS, std::uint64_t(&interrupt_stack_top));
index 7d0f9ff3ba01445b19f1b75a94a9e8f06994cae8..eeef6903a3607bac01260ddee246864a5ff1ceb5 100644 (file)
@@ -1,32 +1,54 @@
 #include "paging.hpp"
 #include "serial.hpp"
 
-// void os::paging::unmap(phys_ptr<PML4T> PLM4T, page* virt, std::uint64_t length) { }
-// void os::paging::map(phys_ptr<PML4T> PLM4T, page* virt, std::uint64_t length, phys_ptr<page> phys) { }
-template<int order> void print_mapping(const os::paging::paging_table<order>& table, std::uint64_t virt_address, bool show_higher_half) {
-       for (std::size_t i = 0; i < (order == 3 && !show_higher_half ? 256 : 512); i++) {
-               const auto& page = table.contents[i];
-               if (!page.P()) { continue; }
-               std::uint64_t new_virt = virt_address + i * (4096ul << (order * 9));
-               new_virt |= ((new_virt & 0x0000800000000000) != 0 ? 0xFFFF000000000000 : 0);
-               if (page.is_page()) {
-                       os::print(new_virt);
-                       os::print(" -> ");
-                       os::print(page.base_address().get_phys_addr());
-                       os::print(" (order ");
-                       os::printc(order + '0');
-                       os::print(")\n");
+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) {
+       for (std::size_t i = 0; i < 512; i++) {
+               if (!PT.contents[i].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);
+       }
+}
+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) {
+       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);
                } else {
-                       if constexpr (order > 0) { // Will never be false when !page.is_page().
-                               print_mapping<order - 1>(*page.base_address(), new_virt, show_higher_half);
-                       }
+                       on_all_pages(*os::paging::get_base_address(PDT.contents[i]), f, virt_address);
                }
        }
 }
-void os::paging::print_mapping(const PML4T& PML4T, bool show_higher_half) {
-       ::print_mapping(PML4T, 0, show_higher_half);
+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) {
+       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);
+               } else {
+                       on_all_pages(*os::paging::get_base_address(PDPT.contents[i]), f, virt_address);
+               }
+       }
+}
+}
+void os::paging::on_all_pages(const os::paging::PML4T& PML4T, void f(page*, phys_ptr<page>, std::size_t)) {
+       for (std::size_t i = 0; i < 512; i++) {
+               if (!PML4T.contents[i].P) {
+                       continue;
+               }
+               std::uint64_t virt_address = (i < 256 ? 0x0000'0000'0000'0000 : 0xFFFF'8000'0000'0000) | (i * 0x1000ull * 512ull * 512ull * 512ull);
+               ::on_all_pages(*os::paging::get_base_address(PML4T.contents[i]), f, virt_address);
+       }
 }
 
+
 os::paging::page one_past_end_page_for_page_allocator;
 os::paging::page_allocator_t os::paging::page_allocator(os::phys_ptr<os::paging::page>(reinterpret_cast<uintptr_t>(&one_past_end_page_for_page_allocator) - 0xFFFFFFFF80000000));
 
index 347733bd78745fec7c2a9ed98b950cf336aa626e..ade4bcb27784cb13e8b7a453d386adb0a0f2e642 100644 (file)
 
 namespace os { namespace paging {
 
-template <int order>
-struct __attribute__((aligned(0x1000))) paging_table;
-
-template <int order>
-struct paging_entry {
-public:
-       static_assert(order >= 0, "negative order for paging entry.");
-       paging_entry(bool is_page) {
-               os::assert(order != 0 || is_page, "4KiB defined as non-page.");
-               if (order != 0 && is_page) {
-                       data |= 1 << 7; // Mark as smallest page.
-               }
-       }
-       inline bool is_page() const {
-               return order == 0 || (data & (1 << 7)) != 0;
-       }
-
-       inline bool NX() const {
-               return (data & (1ul << 63)) != 0;
-       }
-       inline void NX(bool v) {
-               data = (data & ~(1ul << 63)) | (v ? (1ul << 63) : 0);
-       }
-       inline unsigned PK() const {
-               os::assert(is_page(), "read protection key of non-page.");
-               return (data >> 52) & 0xF;
-       }
-       inline void PK(unsigned v) {
-               os::assert(is_page(), "write to protection key of non-page.");
-               os::assert((v & 0xF) == v, "incorrect protection key.");
-               data = (data & ~(0xFul << 59)) | (std::uint64_t(v) << 59);
-       }
-       inline unsigned AVL_high() const {
-               return (data >> 52) & (is_page() ? 0x7F : 0x7FF);
-       }
-       inline void AVL_high(unsigned v) {
-               os::assert((v & (is_page() ? 0x7F : 0x7FF)) == v, "incorrect AVL high bits.");
-               data = (data & ~((is_page() ? 0x7Ful : 0x7FFul) << 52)) | (std::uint64_t(v) << 52);
-       }
-       inline phys_ptr<paging_table<order - 1>> base_address() const {
-               return phys_ptr<paging_table<order - 1>>{data & 0x000FFFFFFFFFF000 & ~(order != 0 && is_page() ? 1ul << 12 : 0ul)};
-       }
-       inline void base_address(phys_ptr<paging_table<order - 1>> v) {
-               const std::uint64_t v_int = v.get_phys_addr();
-               os::assert((v_int & 0x000FFFFFFFFFF000 & (0xFFFFFFFFFFFFF000 << (is_page() ? 9 * order : 0))) == v_int, "incorrect base address.");
-               data = (data & ~0x000FFFFFFFFFF000ul & ~(order != 0 && is_page() ? 1ul << 12 : 0ul)) | v_int;
-       }
-       inline unsigned AVL_low() const {
-               return (data >> 9) & 0x7;
-       }
-       inline void AVL_low(unsigned v) {
-               os::assert((v & 0x7) == v, "incorrect AVL low bits");
-               data = (data & ~(0x7ul << 9)) | (v << 9);
-       }
-       inline bool G() const {
-               os::assert(is_page(), "read global bit of non-page.");
-               return (data & (1 << 8)) != 0;
-       }
-       inline void G(bool v) {
-               os::assert(is_page(), "write to global bit of non-page.");
-               data = (data & ~(1ul << 8)) | (v ? 1 << 8 : 0);
-       }
-       inline bool PAT() const {
-               os::assert(is_page(), "read PAT bit of non-page.");
-               return (data & (1 << (order == 0 ? 7 : 12))) != 0;
-       }
-       inline void PAT(bool v) {
-               os::assert(is_page(), "write to PAT bit of non-page.");
-               data = (data & ~(1ul << (order == 0 ? 7 : 12))) | (v ? 1 << (order == 0 ? 7 : 12) : 0);
-       }
-       inline bool D() const {
-               os::assert(is_page(), "read dirty bit of non-page.");
-               return (data & (1 << 6)) != 0;
-       }
-       inline void D(bool v) {
-               os::assert(is_page(), "write to dirty bit of non-page.");
-               data = (data & ~(1ul << 6)) | (v ? 1 << 6 : 0);
-       }
-       inline bool A() const {
-               return (data & (1 << 5)) != 0;
-       }
-       inline void A(bool v) {
-               data = (data & ~(1ul << 5)) | (v ? 1 << 5 : 0);
-       }
-       inline bool PCD() const {
-               return (data & (1 << 4)) != 0;
-       }
-       inline void PCD(bool v) {
-               data = (data & ~(1ul << 4)) | (v ? 1 << 4 : 0);
-       }
-       inline bool PWT() const {
-               return (data & (1 << 3)) != 0;
-       }
-       inline void PWT(bool v) {
-               data = (data & ~(1ul << 3)) | (v ? 1 << 3 : 0);
-       }
-       inline bool U_S() const {
-               return (data & (1 << 2)) != 0;
-       }
-       inline void U_S(bool v) {
-               data = (data & ~(1ul << 2)) | (v ? 1 << 2 : 0);
-       }
-       inline bool R_W() const {
-               return (data & (1 << 1)) != 0;
-       }
-       inline void R_W(bool v) {
-               data = (data & ~(1ul << 1)) | (v ? 1 << 1 : 0);
-       }
-       inline bool P() const {
-               return (data & (1 << 0)) != 0;
-       }
-       inline void P(bool v) {
-               data = (data & ~(1ul << 0)) | (v ? 1 << 0 : 0);
-       }
-
-private:
-       std::uint64_t data;
+struct PML4E;
+struct PML4T;
+union PDPE;
+struct PDPT;
+union PDE;
+struct PDT;
+struct PE;
+struct PT;
+struct page;
+
+struct __attribute__((packed)) PML4E {
+       std::uint64_t P : 1 = 0;
+       std::uint64_t R_W : 1;
+       std::uint64_t U_S : 1;
+       std::uint64_t PWT : 1;
+       std::uint64_t PCD : 1;
+       std::uint64_t A : 1 = 0;
+       std::uint64_t IGN : 1 = 0;
+       std::uint64_t MBZ : 2 = 0;
+       std::uint64_t AVL_low : 3 = 0;
+       std::uint64_t base_address : 40;
+       std::uint64_t AVL_high : 11 = 0;
+       std::uint64_t NX : 1;
 };
-
-template <int order>
-struct __attribute__((aligned(0x1000))) paging_table {
-       static_assert(order >= 0, "Paging table of negative order.");
-       paging_entry<order> contents[512];
+static_assert(sizeof(PML4E) == 8);
+struct __attribute__((aligned(0x1000))) PML4T {
+       PML4E contents[512];
 };
-static_assert(sizeof(paging_table<0>) == 0x1000);
-static_assert(alignof(paging_table<0>) == 0x1000);
+static_assert(sizeof(PML4T) == 0x1000);
+static_assert(alignof(PML4T) == 0x1000);
 
-template<>
-struct __attribute__((aligned(0x1000))) paging_table<-1> {
+struct __attribute__((aligned(0x1000))) page {
+       char contents[0x1000];
+};
+static_assert(sizeof(page) == 0x1000);
+static_assert(alignof(page) == 0x1000);
+
+union __attribute__((packed)) PDPE {
+       struct __attribute__((packed)) {
+               std::uint64_t P : 1 = 0;
+               std::uint64_t R_W : 1;
+               std::uint64_t U_S : 1;
+               std::uint64_t PWT : 1;
+               std::uint64_t PCD : 1;
+               std::uint64_t A : 1 = 0;
+               std::uint64_t IGN_0 : 1 = 0;
+               std::uint64_t zero : 1 = 0;
+               std::uint64_t IGN_1 : 1 = 0;
+               std::uint64_t AVL_low : 3 = 0;
+               std::uint64_t base_address : 40;
+               std::uint64_t AVL_high : 11 = 0;
+               std::uint64_t NX : 1;
+       } non_page;
+       struct __attribute__((packed)) {
+               std::uint64_t P : 1 = 0;
+               std::uint64_t R_W : 1;
+               std::uint64_t U_S : 1;
+               std::uint64_t PWT : 1;
+               std::uint64_t PCD : 1;
+               std::uint64_t A : 1 = 0;
+               std::uint64_t D : 1 = 0;
+               std::uint64_t one : 1 = 1;
+               std::uint64_t G : 1;
+               std::uint64_t AVL_low : 3 = 0;
+               std::uint64_t PAT : 1;
+               std::uint64_t reserved : 17 = 0;
+               std::uint64_t base_address : 22;
+               std::uint64_t AVL_high : 7 = 0;
+               std::uint64_t AVL_or_MPK : 4;
+               std::uint64_t NX : 1;
+       } page;
+};
+static_assert(sizeof(PDPE) == 8);
+struct __attribute__((aligned(0x1000))) PDPT {
+       PDPE contents[512];
+};
+static_assert(sizeof(PDPT) == 0x1000);
+static_assert(alignof(PDPT) == 0x1000);
+
+union __attribute__((packed)) PDE {
+       struct __attribute__((packed)) {
+               std::uint64_t P : 1 = 0;
+               std::uint64_t R_W : 1;
+               std::uint64_t U_S : 1;
+               std::uint64_t PWT : 1;
+               std::uint64_t PCD : 1;
+               std::uint64_t A : 1 = 0;
+               std::uint64_t IGN_0 : 1 = 0;
+               std::uint64_t zero : 1 = 0;
+               std::uint64_t IGN_1 : 1 = 0;
+               std::uint64_t AVL_low : 3 = 0;
+               std::uint64_t base_address : 40;
+               std::uint64_t AVL_high : 11 = 0;
+               std::uint64_t NX : 1;
+       } non_page;
+       struct __attribute__((packed)) {
+               std::uint64_t P : 1 = 0;
+               std::uint64_t R_W : 1;
+               std::uint64_t U_S : 1;
+               std::uint64_t PWT : 1;
+               std::uint64_t PCD : 1;
+               std::uint64_t A : 1 = 0;
+               std::uint64_t D : 1 = 0;
+               std::uint64_t one : 1 = 1;
+               std::uint64_t G : 1;
+               std::uint64_t AVL_low : 3 = 0;
+               std::uint64_t PAT : 1;
+               std::uint64_t reserved : 8 = 0;
+               std::uint64_t base_address : 31;
+               std::uint64_t AVL_high : 7 = 0;
+               std::uint64_t AVL_or_MPK : 4 = 0;
+               std::uint64_t NX : 1;
+       } page;
+};
+static_assert(sizeof(PDE) == 8);
+struct __attribute__((aligned(0x1000))) PDT {
+       PDE contents[512];
+};
+static_assert(sizeof(PDT) == 0x1000);
+static_assert(alignof(PDT) == 0x1000);
+
+struct __attribute__((packed)) PE {
+       std::uint64_t P : 1 = 0;
+       std::uint64_t R_W : 1;
+       std::uint64_t U_S : 1;
+       std::uint64_t PWT : 1;
+       std::uint64_t PCD : 1;
+       std::uint64_t A : 1 = 0;
+       std::uint64_t D : 1 = 0;
+       std::uint64_t PAT : 1;
+       std::uint64_t G : 1;
+       std::uint64_t AVL_low : 3 = 0;
+       std::uint64_t base_address : 40;
+       std::uint64_t AVL_high : 7 = 0;
+       std::uint64_t AVL_or_MPK : 4 = 0;
+       std::uint64_t NX : 1;
+};
+static_assert(sizeof(PE) == 8);
+struct __attribute__((aligned(0x1000))) PT {
+       PE contents[512];
 };
-static_assert(sizeof(paging_table<-1>) == 0x1000);
-static_assert(alignof(paging_table<-1>) == 0x1000);
-
-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>;
-using page = paging_table<-1>;
-
-void unmap(phys_ptr<PML4T> PLM4T, page* virt, std::uint64_t length);
-void map(phys_ptr<PML4T> PLM4T, page* virt, std::uint64_t length, phys_ptr<page> phys);
-void print_mapping(const PML4T& PML4T, bool show_higher_half = false);
+static_assert(sizeof(PT) == 0x1000);
+static_assert(alignof(PT) == 0x1000);
+
+
+inline bool is_page(const PML4E __attribute__((unused))& PML4E) { return false; }
+inline bool is_page(const PDPE& PDPE) { return PDPE.page.one == 1; }
+inline bool is_page(const PDE& PDE) { return PDE.page.one == 1; }
+inline bool is_page(const PE __attribute__((unused))& PE) { return true; }
+
+inline phys_ptr<PDPT> get_base_address(const PML4E& PML4E) {
+       os::assert(!is_page(PML4E), "Tried to get non-page out of a page paging.");
+       return phys_ptr<PDPT>{PML4E.base_address * 0x1000ull};
+}
+inline phys_ptr<PDT> get_base_address(const PDPE& PDPE) {
+       os::assert(!is_page(PDPE), "Tried to get non-page out of a page paging.");
+       return phys_ptr<PDT>{PDPE.non_page.base_address * 0x1000ull};
+}
+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) {
+       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};
+}
+inline phys_ptr<page> 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};
+}
+inline phys_ptr<page> 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.base_address * 0x1000ull};
+}
+
+inline void set_base_address(PML4E& PML4E, phys_ptr<PDPT> ptr) {
+       os::assert(!is_page(PML4E), "Tried to get non-page out of a page paging.");
+       PML4E.base_address = ptr.get_phys_addr() / 0x1000ull;
+}
+inline void set_base_address(PDPE& PDPE, phys_ptr<PDT> ptr) {
+       os::assert(!is_page(PDPE), "Tried to get non-page out of a page paging.");
+       PDPE.non_page.base_address = ptr.get_phys_addr() / 0x1000ull;
+}
+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) {
+       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;
+}
+inline void set_page_base_address(PDE& PDE, phys_ptr<page> 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;
+}
+inline void set_page_base_address(PE& PE, phys_ptr<page> ptr) {
+       os::assert(is_page(PE), "Tried to get page out of a non-page paging.");
+       PE.base_address = ptr.get_phys_addr() / 0x1000ull;
+}
+
+// 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));
 
 class page_allocator_t;
 extern page_allocator_t page_allocator;