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;
}
}
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;
}
}
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);
}
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()));
}
{
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);
};
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);
}
}