std::byte* os::paging::setup_page(os::paging::PML4T& PML4T, const void* vaddr, bool R_W, bool U_S) {
const auto indices = os::paging::calc_page_table_indices(vaddr);
- if (PML4T.contents[indices.pml4e].P == 0) {
- PML4T.contents[indices.pml4e] = {.P = 1, .R_W = 1, .U_S = U_S, .PWT = 0, .PCD = 0, .base_address = 0, .NX = 0};
+ if (PML4T.contents[indices.pml4e].non_page.P == 0) {
+ PML4T.contents[indices.pml4e] = {.non_page = {.P = 1, .R_W = 1, .U_S = U_S, .PWT = 0, .PCD = 0, .base_address = 0, .NX = 0}};
const auto PDPT_alloc = os::paging::page_allocator.allocate(1);
memset((void*)PDPT_alloc.ptr, 0, 0x1000);
set_base_address(PML4T.contents[indices.pml4e], os::phys_ptr<os::paging::PDPT>(PDPT_alloc.ptr.get_phys_addr()));
"Cannot map memory address 0x{} because it is inside a 2MiB page", std::uintptr_t(vaddr));
}
os::paging::PT& PT = *get_base_address(PDT.contents[indices.pde]);
- os::assert(PT.contents[indices.pe].P == 0, "Memory at address 0x{} has already been mapped.", std::uintptr_t(vaddr));
+ os::assert(PT.contents[indices.pe].page.P == 0, "Memory at address 0x{} has already been mapped.", std::uintptr_t(vaddr));
PT.contents[indices.pe] =
- {.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};
+ {.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()));
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) {
+ if (!PT.contents[i].page.P) {
continue;
}
std::uint64_t virt_address = PT_virt_address | (i * 0x1000ull);
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) {
+ if (!PML4T.contents[i].non_page.P) {
continue;
}
std::uint64_t virt_address = (i < 256 ? 0x0000'0000'0000'0000 : 0xFFFF'8000'0000'0000) | (i * 0x1000ull * 512ull * 512ull * 512ull);
namespace os { namespace paging {
-struct PML4E;
-struct PML4T;
-union PDPE;
-struct PDPT;
-union PDE;
-struct PDT;
-struct PE;
-struct PT;
-struct page;
-
-struct 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 <std::size_t depth> struct paging_entry;
+template <std::size_t depth> struct __attribute__((aligned(0x1000))) paging_table {
+ paging_entry<depth> contents[512];
};
-static_assert(sizeof(PML4E) == 8);
-struct __attribute__((aligned(0x1000))) PML4T {
- PML4E contents[512];
+template <> struct __attribute__((aligned(0x1000))) paging_table<0> {
+ std::byte contents[4096];
};
-static_assert(sizeof(PML4T) == 0x1000);
-static_assert(alignof(PML4T) == 0x1000);
+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>;
-struct __attribute__((aligned(0x1000))) page {
- char contents[0x1000];
+template<> struct paging_entry<4> {
+ struct {
+ 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;
+ } non_page;
};
-static_assert(sizeof(page) == 0x1000);
-static_assert(alignof(page) == 0x1000);
+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);
-union PDPE {
+template<> struct paging_entry<3> {
+union {
struct {
std::uint64_t P : 1 = 0;
std::uint64_t R_W : 1;
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);
+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);
-union PDE {
+template <> struct paging_entry<2> {
+union {
struct {
std::uint64_t P : 1 = 0;
std::uint64_t R_W : 1;
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);
+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);
-struct 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];
+template <> struct paging_entry<1> {
+ struct {
+ 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;
+ } page;
};
-static_assert(sizeof(PT) == 0x1000);
-static_assert(alignof(PT) == 0x1000);
+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);
inline bool is_page(const PML4E __attribute__((unused))& PML4E) { return false; }
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};
+ return phys_ptr<PDPT>{PML4E.non_page.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.");
}
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};
+ return phys_ptr<page>{PE.page.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;
+ PML4E.non_page.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.");
}
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;
+ PE.page.base_address = ptr.get_phys_addr() / 0x1000ull;
}
struct page_table_indices {