From: Amelia Coutard Date: Thu, 13 Oct 2022 09:26:43 +0000 (+0200) Subject: Changed the page tables to use bitfields X-Git-Url: https://git.ameliathe1st.gay/?a=commitdiff_plain;h=4f7b1055a5147493d2935e23e0b44690000290a0;p=voyage-au-centre-des-fichiers.git Changed the page tables to use bitfields --- diff --git a/src/kernel.cpp b/src/kernel.cpp index 850c108..76d5167 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -133,17 +133,15 @@ extern "C" void kmain(unsigned long magic, os::phys_ptrcontents[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)); diff --git a/src/paging.cpp b/src/paging.cpp index 7d0f9ff..eeef690 100644 --- a/src/paging.cpp +++ b/src/paging.cpp @@ -1,32 +1,54 @@ #include "paging.hpp" #include "serial.hpp" -// void os::paging::unmap(phys_ptr PLM4T, page* virt, std::uint64_t length) { } -// void os::paging::map(phys_ptr PLM4T, page* virt, std::uint64_t length, phys_ptr phys) { } -template void print_mapping(const os::paging::paging_table& 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, 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(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, 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(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(*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, 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(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, 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(reinterpret_cast(&one_past_end_page_for_page_allocator) - 0xFFFFFFFF80000000)); diff --git a/src/paging.hpp b/src/paging.hpp index 347733b..ade4bcb 100644 --- a/src/paging.hpp +++ b/src/paging.hpp @@ -7,152 +7,208 @@ namespace os { namespace paging { -template -struct __attribute__((aligned(0x1000))) paging_table; - -template -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> base_address() const { - return phys_ptr>{data & 0x000FFFFFFFFFF000 & ~(order != 0 && is_page() ? 1ul << 12 : 0ul)}; - } - inline void base_address(phys_ptr> 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 -struct __attribute__((aligned(0x1000))) paging_table { - static_assert(order >= 0, "Paging table of negative order."); - paging_entry 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 PLM4T, page* virt, std::uint64_t length); -void map(phys_ptr PLM4T, page* virt, std::uint64_t length, phys_ptr 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 get_base_address(const PML4E& PML4E) { + os::assert(!is_page(PML4E), "Tried to get non-page out of a page paging."); + return phys_ptr{PML4E.base_address * 0x1000ull}; +} +inline phys_ptr get_base_address(const PDPE& PDPE) { + os::assert(!is_page(PDPE), "Tried to get non-page out of a page paging."); + return phys_ptr{PDPE.non_page.base_address * 0x1000ull}; +} +inline phys_ptr get_base_address(const PDE& PDE) { + os::assert(!is_page(PDE), "Tried to get non-page out of a page paging."); + return phys_ptr{PDE.non_page.base_address * 0x1000ull}; +} +inline phys_ptr 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{PDPE.page.base_address * 0x1000ull * 512ull * 512ull}; +} +inline phys_ptr 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{PDE.page.base_address * 0x1000ull * 512ull}; +} +inline phys_ptr 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{PE.base_address * 0x1000ull}; +} + +inline void set_base_address(PML4E& PML4E, phys_ptr 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 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 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 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 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 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, std::size_t)); class page_allocator_t; extern page_allocator_t page_allocator;