From: Amelia Coutard <eliottulio.coutard@gmail.com>
Date: Sat, 16 Dec 2023 00:35:31 +0000 (+0100)
Subject: Simplification des structures qui gèrent la mémoire virtuelle
X-Git-Url: https://git.ameliathe1st.gay/?a=commitdiff_plain;h=7a53af1b8da6a0d3848bc6f10f1e9ce658b5b614;p=voyage-au-centre-des-fichiers.git

Simplification des structures qui gèrent la mémoire virtuelle
---

diff --git a/kernel/src/elf64.cpp b/kernel/src/elf64.cpp
index e4de1cd..1223fcc 100644
--- a/kernel/src/elf64.cpp
+++ b/kernel/src/elf64.cpp
@@ -33,7 +33,9 @@ void os::elf::load_elf(os::process& result, std::byte* start, std::size_t length
 	constexpr std::size_t stack_size = 16 * 0x1000 /* 64KiB */;
 	std::byte* const stack = (std::byte*)0x0000'8000'0000'0000 - stack_size;
 
-	result.PML4T = phys_ptr<paging::PML4T>(os::paging::page_allocator.allocate(1).ptr.get_phys_addr());
+	const auto page = os::paging::page_allocator.allocate(1);
+	os::assert(page.ptr != nullptr, "Not enough memory for elf file loading.");
+	result.PML4T = phys_ptr<paging::PML4T>(page.ptr.get_phys_addr());
 	result.rip = std::uint64_t(elf_header.entry);
 	result.rsp = std::uint64_t(stack + stack_size);
 	result.rax = 0;
@@ -75,8 +77,11 @@ void os::elf::load_elf(os::process& result, std::byte* start, std::size_t length
 		for (std::size_t i = 0; i < nb_pages; i++) {
 			auto const alloc = os::paging::page_allocator.allocate(1);
 			os::assert(alloc.ptr != nullptr, "Failed to allocate enough memory for loading of elf binary.");
-			os::paging::map_page(*result.PML4T, (os::paging::page<0>*)(program_header.p_vaddr + i * 0x1000), alloc.ptr,
-				{.R_W = (program_header.flags & 2) >> 1, .U_S = 1, .PWT = 0, .PCD = 0, .PAT = 0, .G = 0, .base_address = 0, .NX = 1 - (program_header.flags & 1)});
+			os::paging::map_page(*result.PML4T, (os::paging::page<0>*)(program_header.p_vaddr + i * 0x1000), alloc.ptr, {
+				.RW = ((program_header.flags & 2) >> 1) != 0,
+				.US = true, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = false, .AVL = 0,
+				.NX = (program_header.flags & 1) == 0,
+			});
 			memcpy((void*)alloc.ptr, start + program_header.p_offset, clamp(0ul, program_header.p_filesz - i * 0x1000, 0x1000ul));
 		}
 	}
diff --git a/kernel/src/interrupts.cpp b/kernel/src/interrupts.cpp
index 028a672..a2b6def 100644
--- a/kernel/src/interrupts.cpp
+++ b/kernel/src/interrupts.cpp
@@ -114,7 +114,7 @@ extern "C" void int_page_fault(std::uint32_t err_code, std::uint64_t vaddr) {
 		auto const alloc = os::paging::page_allocator.allocate(1);
 		os::assert(alloc.ptr != nullptr, "Out of memory.");
 		os::paging::map_page(os::paging::global_PML4T, (os::paging::page<0>*)vaddr, alloc.ptr,
-			{.R_W = 1, .U_S = 0, .PWT = 0, .PCD = 0, .PAT = 0, .G = 1, .base_address = 0, .NX = 1});
+			{.RW = true, .US = false, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = true, .AVL = 0, .NX = true});
 		return;
 	} else if (
 		(0x0000'7FFF'FFFF'0000 <= vaddr && vaddr < 0x0000'8000'0000'0000) // stack
@@ -123,7 +123,7 @@ extern "C" void int_page_fault(std::uint32_t err_code, std::uint64_t vaddr) {
 		auto const alloc = os::paging::page_allocator.allocate(1);
 		os::assert(alloc.ptr != nullptr, "Out of memory.");
 		os::paging::map_page(*os::get_process(os::current_pid).PML4T, (os::paging::page<0>*)vaddr, alloc.ptr,
-			{.R_W = 1, .U_S = 1, .PWT = 0, .PCD = 0, .PAT = 0, .G = 0, .base_address = 0, .NX = 1});
+			{.RW = true, .US = true, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = false, .AVL = 0, .NX = true});
 		return;
 	}
 	os::print("Interrupt: Page Fault.\n");
diff --git a/kernel/src/kernel.cpp b/kernel/src/kernel.cpp
index cc4d0c1..f1c1459 100644
--- a/kernel/src/kernel.cpp
+++ b/kernel/src/kernel.cpp
@@ -50,30 +50,30 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 	for (std::size_t i = std::size_t(&_kernel_phys_start); i < std::size_t(&_kernel_phys_rw_start); ) {
 		if (i % (1024 * 1024 * 1024) == 0 && i + 1024 * 1024 * 1024 < std::size_t(&_kernel_phys_rw_start)) {
 			os::paging::map_page<2, 3>(os::paging::global_PML4T, (os::paging::page<2>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr<os::paging::page<2>>(i),
-				{ .R_W = 0, .U_S = 0, .PWT = 0, .PCD = 0, .G = 1, .PAT = 0, .base_address = 0, .NX = 0 });
+				{ .RW = false, .US = false, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = true, .AVL = 0, .NX = false });
 			i += 1024 * 1024 * 1024;
 		} else if (i % (1024 * 1024 * 2) == 0 && i + 1024 * 1024 * 2 < std::size_t(&_kernel_phys_rw_start)) {
 			os::paging::map_page<1, 3>(os::paging::global_PML4T, (os::paging::page<1>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr<os::paging::page<1>>(i),
-				{ .R_W = 0, .U_S = 0, .PWT = 0, .PCD = 0, .G = 1, .PAT = 0, .base_address = 0, .NX = 0 });
+				{ .RW = false, .US = false, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = true, .AVL = 0, .NX = false });
 			i += 1024 * 1024 * 2;
 		} else {
 			os::paging::map_page<0, 3>(os::paging::global_PML4T, (os::paging::page<0>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr<os::paging::page<0>>(i),
-				{ .R_W = 0, .U_S = 0, .PWT = 0, .PCD = 0, .PAT = 0, .G = 1, .base_address = 0, .NX = 0 });
+				{ .RW = false, .US = false, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = true, .AVL = 0, .NX = false });
 			i += 1024 * 4;
 		}
 	}
 	for (std::size_t i = std::size_t(&_kernel_phys_rw_start); i < std::size_t(&_kernel_phys_end); ) {
 		if (i % (1024 * 1024 * 1024) == 0 && i + 1024 * 1024 * 1024 < std::size_t(&_kernel_phys_rw_start)) {
 			os::paging::map_page<2, 3>(os::paging::global_PML4T, (os::paging::page<2>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr<os::paging::page<2>>(i),
-				{ .R_W = 1, .U_S = 0, .PWT = 0, .PCD = 0, .G = 1, .PAT = 0, .base_address = 0, .NX = 1 });
+				{ .RW = true, .US = false, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = true, .AVL = 0, .NX = true });
 			i += 1024 * 1024 * 1024;
 		} else if (i % (1024 * 1024 * 2) == 0 && i + 1024 * 1024 * 2 < std::size_t(&_kernel_phys_rw_start)) {
 			os::paging::map_page<1, 3>(os::paging::global_PML4T, (os::paging::page<1>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr<os::paging::page<1>>(i),
-				{ .R_W = 1, .U_S = 0, .PWT = 0, .PCD = 0, .G = 1, .PAT = 0, .base_address = 0, .NX = 1 });
+				{ .RW = true, .US = false, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = true, .AVL = 0, .NX = true });
 			i += 1024 * 1024 * 2;
 		} else {
 			os::paging::map_page<0, 3>(os::paging::global_PML4T, (os::paging::page<0>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr<os::paging::page<0>>(i),
-				{ .R_W = 1, .U_S = 0, .PWT = 0, .PCD = 0, .PAT = 0, .G = 1, .base_address = 0, .NX = 1 });
+				{ .RW = true, .US = false, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = true, .AVL = 0, .NX = true });
 			i += 1024 * 4;
 		}
 	}
@@ -100,19 +100,22 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 							os::paging::global_PML4T,
 							(os::paging::page<2>*)(0xFFFF'8000'0000'0000 + j),
 							os::phys_ptr<os::paging::page<2>>(j),
-							{ .R_W = 1, .U_S = 0, .PWT = 0, .PCD = 0, .G = 1, .PAT = 0, .base_address = 0, .NX = 1 });
+							{ .RW = true, .US = false, .PWT = false, .PCD = false, .A = false, .D = false,
+							  .PAT = false, .G = true, .AVL = 0, .NX = true });
 						j += 1024 * 1024 * 1024;
 					} else if (j % (1024 * 1024 * 2) == 0 && j + 1024 * 1024 * 2 < e) {
 						os::paging::map_page<1, 3>(os::paging::global_PML4T,
 							(os::paging::page<1>*)(0xFFFF'8000'0000'0000 + j),
 							os::phys_ptr<os::paging::page<1>>(j),
-							{ .R_W = 1, .U_S = 0, .PWT = 0, .PCD = 0, .G = 1, .PAT = 0, .base_address = 0, .NX = 1 });
+							{ .RW = true, .US = false, .PWT = false, .PCD = false, .A = false, .D = false,
+							  .PAT = false, .G = true, .AVL = 0, .NX = true });
 						j += 1024 * 1024 * 2;
 					} else {
 						os::paging::map_page<0, 3>(os::paging::global_PML4T,
 							(os::paging::page<0>*)(0xFFFF'8000'0000'0000 + j),
 							os::phys_ptr<os::paging::page<0>>(j),
-							{ .R_W = 1, .U_S = 0, .PWT = 0, .PCD = 0, .PAT = 0, .G = 1, .base_address = 0, .NX = 1 });
+							{ .RW = true, .US = false, .PWT = false, .PCD = false, .A = false, .D = false,
+							  .PAT = false, .G = true, .AVL = 0, .NX = true });
 						j += 1024 * 4;
 					}
 				}
@@ -166,7 +169,7 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 		os::paging::map_page<0, 3>(os::paging::global_PML4T,
 			(os::paging::page<0>*)(0xFFFF'8000'fee0'0000),
 			os::phys_ptr<os::paging::page<0>>(0x0000'0000'fee0'0000),
-			{ .R_W = 1, .U_S = 0, .PWT = 0, .PCD = 1, .PAT = 0, .G = 1, .base_address = 0, .NX = 1 });
+			{ .RW = true, .US = false, .PWT = false, .PCD = true, .A = false, .D = false, .PAT = false, .G = true, .AVL = 0, .NX = true });
 		os::enable_interrupts(isr_info, idt);
 	}
 
@@ -175,10 +178,10 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 	static_assert(sizeof(os::processes) <= 1024 * 1024 * 1024, "Error: processes array too big.");
 	{
 		std::size_t const index = (std::uint64_t(&os::processes) >> (12 + 9 * 3)) & 0x1FF;
-		os::paging::global_PML4T.contents[index] = {.non_page = {.P = 1, .R_W = 1, .U_S = 0, .PWT = 0, .PCD = 0, .base_address = 0, .NX = 0}};
+		os::paging::global_PML4T.contents[index].paging_table_info({.RW = true, .US = false, .PWT = false, .PCD = false, .A = false, .AVL = 0, .NX = false});
 		const auto PDPT_alloc = os::paging::page_allocator.allocate(1);
 		os::memset((void*)PDPT_alloc.ptr, 0, 0x1000);
-		set_base_address(os::paging::global_PML4T.contents[index], os::phys_ptr<os::paging::PDPT>(PDPT_alloc.ptr.get_phys_addr()));
+		os::paging::global_PML4T.contents[index].paging_table_ptr(os::phys_ptr<os::paging::PDPT>(PDPT_alloc.ptr.get_phys_addr()));
 	}
 
 	{
diff --git a/kernel/src/paging.hpp b/kernel/src/paging.hpp
index a5d4237..e085523 100644
--- a/kernel/src/paging.hpp
+++ b/kernel/src/paging.hpp
@@ -21,186 +21,168 @@
 namespace os { namespace paging {
 
 template <std::size_t depth> struct paging_entry;
+template <std::size_t depth> struct paging_table;
+template <std::size_t depth> struct page;
+
+struct page_info {
+	bool RW;
+	bool US;
+	bool PWT;
+	bool PCD;
+	bool A;
+	bool D;
+	bool PAT;
+	bool G;
+	std::uint16_t AVL; // Only 14 bits, actually.
+	bool NX;
+};
+struct paging_table_info {
+	bool RW;
+	bool US;
+	bool PWT;
+	bool PCD;
+	bool A;
+	std::uint16_t AVL; // Really 16 bits !
+	bool NX;
+};
+
+template <std::size_t depth> struct paging_entry {
+	std::uint64_t data = 0;
+
+	bool is_present() {
+		return (data & (1 << 0)) != 0;
+	}
+	bool is_page() {
+		os::assert(is_present(), "Cannot check if a paging_entry is a page if it's not present.");
+		return depth == 0 || (data & (1 << 7)) != 0;
+	}
+
+	paging::page_info page_info() {
+		os::assert(is_page(), "Cannot access page info for a non-page.");
+		return {
+			.RW = (data & (1ull << 1)) != 0,
+			.US = (data & (1ull << 2)) != 0,
+			.PWT = (data & (1ull << 3)) != 0,
+			.PCD = (data & (1ull << 4)) != 0,
+			.A = (data & (1ull << 5)) != 0,
+			.D = (data & (1ull << 6)) != 0,
+			.PAT = depth == 0
+				? (data & (1ull << 7)) != 0
+				: (data & (1ull << 12)) != 0,
+			.G = (data & (1ull << 8)) != 0,
+			.AVL = ((data >> 9) & 0x7)
+				| (((data >> 52) & 0x7FF) << 3),
+			.NX = (data & (1ull << 63)) != 0,
+		};
+	}
+	os::phys_ptr<os::paging::page<depth>> page_ptr() {
+		os::assert(is_page(), "Cannot access page physical pointer for a non-page.");
+		std::uintptr_t addr = data & (depth == 0 ? 0x0000'FFFF'FFFF'F000 : 0x0000'FFFF'FFFF'E000);
+		return os::phys_ptr<os::paging::page<depth>>(addr | ((addr & 0x0000'8000'0000'0000) != 0 ? 0xFFFF'8000'0000'0000 : 0));
+	}
+	void page_ptr(os::phys_ptr<os::paging::page<depth>> page) {
+		os::assert(is_page(), "Cannot access page physical pointer for a non-page.");
+		if (depth == 0) {
+			data = (data & ~0x0000'FFFF'FFFF'F000) | page.get_phys_addr();
+		} else {
+			data = (data & ~0x0000'FFFF'FFFF'E000) | page.get_phys_addr();
+		}
+	}
+	paging::paging_table_info paging_table_info() {
+		os::assert(!is_page(), "Cannot access paging table info for a page.");
+		return {
+			.RW = (data & (1ull << 1)) != 0,
+			.US = (data & (1ull << 2)) != 0,
+			.PWT = (data & (1ull << 3)) != 0,
+			.PCD = (data & (1ull << 4)) != 0,
+			.A = (data & (1ull << 5)) != 0,
+			.AVL = ((data >> 6) & 0x1)
+				| (((data >> 8) & 0xF) << 1)
+				| (((data >> 52) & 0x7FF) << 5),
+			.NX = (data & (1ull << 63)) != 0,
+		};
+	}
+	os::phys_ptr<os::paging::paging_table<depth - 1>> paging_table_ptr() {
+		os::assert(!is_page(), "Cannot access paging table physical pointer for a page.");
+		std::uintptr_t addr = data & 0x0000'FFFF'FFFF'F000;
+		return os::phys_ptr<os::paging::paging_table<depth - 1>>(addr | ((addr & 0x0000'8000'0000'0000) != 0 ? 0xFFFF'8000'0000'0000 : 0));
+	}
+	void paging_table_ptr(os::phys_ptr<os::paging::paging_table<depth - 1>> table) {
+		os::assert(!is_page(), "Cannot access paging table physical pointer for a page.");
+		data = (data & ~0x0000'FFFF'FFFF'F000) | table.get_phys_addr();
+	}
+	void remove() {
+		data = 0;
+	}
+	void page_info(os::paging::page_info info) {
+		data = (1ull << 0) // P
+		     | (depth != 0 ? (1 << 7) : 0) // Because it is a large page.
+		     | (info.RW ? (1ull << 1) : 0)
+		     | (info.US ? (1ull << 2) : 0)
+		     | (info.PWT ? (1ull << 3) : 0)
+		     | (info.PCD ? (1ull << 4) : 0)
+		     | (info.A ? (1ull << 5) : 0)
+		     | (info.D ? (1ull << 6) : 0)
+		     | (info.PAT ? (depth == 0 ? 1 << 7: 1 << 12) : 0)
+		     | (info.G ? (1ull << 8) : 0)
+		     | (std::uint64_t(info.AVL & 0x7) << 9)
+		     | (std::uint64_t(info.AVL & 0x3FF8) << 49)
+		     | (info.NX ? (1ull << 63) : 0);
+	}
+	void paging_table_info(os::paging::paging_table_info info) {
+		data = (1ull << 0) // P
+		     | (info.RW ? (1ull << 1) : 0)
+		     | (info.US ? (1ull << 2) : 0)
+		     | (info.PWT ? (1ull << 3) : 0)
+		     | (info.PCD ? (1ull << 4) : 0)
+		     | (info.A ? (1ull << 5) : 0)
+		     | (std::uint64_t(info.AVL & 0x1) << 6)
+		     | (std::uint64_t(info.AVL & 0x1E) << 7)
+		     | (std::uint64_t(info.AVL & 0xFFE0) << 47)
+		     | (info.NX ? (1ull << 63) : 0);
+	}
+};
 template <std::size_t depth> struct __attribute__((aligned(0x1000))) paging_table {
 	paging_entry<depth> contents[512];
 };
-
-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);
-
-extern PML4T global_PML4T;
-
-template<> struct paging_entry<3> {
-	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(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<2> {
-union {
-	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_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 {
-		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 = 0;
-		std::uint64_t NX : 1;
-	} 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);
-
-template <> struct paging_entry<1> {
-union {
-	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_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 {
-		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(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<0> {
-	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(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);
 
+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>;
 
-inline bool is_page(PML4E) { return false; }
-inline bool is_page(PDPE PDPE) { return PDPE.page.one == 1; }
-inline bool is_page(PDE PDE) { return PDE.page.one == 1; }
-inline bool is_page(PE) { return true; }
-inline bool is_present(PML4E PML4E) { return PML4E.non_page.P == 1; }
-inline bool is_present(PDPE PDPE) { return PDPE.page.P == 1; }
-inline bool is_present(PDE PDE) { return PDE.page.P == 1; }
-inline bool is_present(PE PE) { return PE.page.P == 1; }
-
-template <size_t depth> phys_ptr<paging_table<depth - 1>> get_base_address(paging_entry<depth> entry) {
-	os::assert(!is_page(entry), "Tried to get non-page out of a page paging.");
-	return phys_ptr<paging_table<depth - 1>>{entry.non_page.base_address * 0x1000ull};
-}
-template <size_t depth> phys_ptr<page<depth>> get_page_base_address(paging_entry<depth> entry) {
-	os::assert(is_page(entry), "Tried to get page out of a non-page paging.");
-	return phys_ptr<page<depth>>{entry.page.base_address * sizeof(page<depth>)};
-}
-
-template <size_t depth> void set_base_address(paging_entry<depth>& entry, phys_ptr<paging_table<depth - 1>> ptr) {
-	os::assert(!is_page(entry), "Tried to get non-page out of a page paging.");
-	entry.non_page.base_address = ptr.get_phys_addr() / 0x1000ull;
-}
-template <size_t depth> void set_page_base_address(paging_entry<depth>& entry, phys_ptr<page<depth>> ptr) {
-	os::assert(is_page(entry), "Tried to get page out of a non-page paging.");
-	entry.page.base_address = ptr.get_phys_addr() / sizeof(page<depth>);
-}
+extern PML4T global_PML4T;
 
 template <std::size_t depth, std::size_t paging_depth = 3>
-void map_page(paging_table<paging_depth>& paging_table, page<depth> const* vaddr, phys_ptr<page<depth>> paddr, decltype(paging_entry<depth>::page) page_info);
+void map_page(paging_table<paging_depth>& paging_table, page<depth> const* vaddr, phys_ptr<page<depth>> paddr, os::paging::page_info page_info);
 template <std::size_t depth>
 void on_all_pages(const paging_table<depth>& paging_table, auto f, std::size_t vaddr_offset = 0);
 
@@ -235,25 +217,25 @@ private:
 };
 
 template <std::size_t depth, std::size_t paging_depth>
-void map_page(paging_table<paging_depth>& paging_table, page<depth> const* vaddr, phys_ptr<page<depth>> paddr, decltype(paging_entry<depth>::page) page_info) {
+void map_page(paging_table<paging_depth>& paging_table, page<depth> const* vaddr, phys_ptr<page<depth>> paddr, os::paging::page_info page_info) {
 	std::size_t const index = (std::uint64_t(vaddr) >> (12 + 9 * paging_depth)) & 0x1FF;
 	if constexpr (depth == paging_depth) {
-		os::assert(paging_table.contents[index].page.P == 0, "Virtual address 0x{} is already mapped.", vaddr);
-		paging_table.contents[index].page = page_info;
-		paging_table.contents[index].page.P = 1;
-		set_page_base_address(paging_table.contents[index], paddr);
+		os::assert(!paging_table.contents[index].is_present(), "Virtual address 0x{} is already mapped.", vaddr);
+		paging_table.contents[index].page_info(page_info);
+		paging_table.contents[index].page_ptr(paddr);
 		invlpg(vaddr);
 	} else {
-		if (paging_table.contents[index].non_page.P == 1) {
-			assert(!is_page(paging_table.contents[index]), "Virtual address 0x{} is already in a mapped page.", vaddr);
+		if (paging_table.contents[index].is_present()) {
+			assert(!paging_table.contents[index].is_page(), "Virtual address 0x{} is already in a mapped page.", vaddr);
 		} else {
 			auto const alloc = page_allocator.allocate(1);
 			assert(alloc.ptr != nullptr, "Not enough RAM to create the paging structures.");
 			memset((void*)alloc.ptr, 0, 0x1000);
-			paging_table.contents[index].non_page = {.P = 1, .R_W = 1, .U_S = page_info.U_S, .PWT = 0, .PCD = 0, .base_address = 0, .NX = 0};
-			set_base_address(paging_table.contents[index], os::phys_ptr<os::paging::paging_table<paging_depth - 1>>{alloc.ptr.get_phys_addr()});
+			paging_table.contents[index].paging_table_info(
+				{.RW = true, .US = page_info.US, .PWT = false, .PCD = false, .A = false, .AVL = 0, .NX = false});
+			paging_table.contents[index].paging_table_ptr(os::phys_ptr<os::paging::paging_table<paging_depth - 1>>{alloc.ptr.get_phys_addr()});
 		}
-		map_page<depth, paging_depth - 1>(*get_base_address(paging_table.contents[index]), vaddr, paddr, page_info);
+		map_page<depth, paging_depth - 1>(*paging_table.contents[index].paging_table_ptr(), vaddr, paddr, page_info);
 	}
 }