os::paging::PML4T os::paging::global_PML4T;
-namespace {
-void on_all_pages(const os::paging::PT& PT, void f(os::paging::page<0>*, os::phys_ptr<os::paging::page<0>>, std::size_t), std::size_t PT_virt_address) {
- for (std::size_t i = 0; i < 512; i++) {
- if (!PT.contents[i].page.P) {
- continue;
- }
- std::uint64_t virt_address = PT_virt_address | (i * 0x1000ull);
- f(reinterpret_cast<os::paging::page<0>*>(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<0>*, os::phys_ptr<os::paging::page<0>>, 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<0>*>(virt_address),
- os::phys_ptr<os::paging::page<0>>(os::paging::get_page_base_address(PDT.contents[i]).get_phys_addr()), 0x1000ull * 512ull);
- } else {
- on_all_pages(*os::paging::get_base_address(PDT.contents[i]), f, virt_address);
- }
- }
-}
-void on_all_pages(const os::paging::PDPT& PDPT, void f(os::paging::page<0>*, os::phys_ptr<os::paging::page<0>>, 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<0>*>(virt_address),
- os::phys_ptr<os::paging::page<0>>(os::paging::get_page_base_address(PDPT.contents[i]).get_phys_addr()), 0x1000ull * 512ull * 512ull);
- } else {
- on_all_pages(*os::paging::get_base_address(PDPT.contents[i]), f, virt_address);
- }
- }
-}
-
-} // namespace
-
-void os::paging::on_all_pages(const os::paging::PML4T& PML4T, void f(page<0>*, phys_ptr<page<0>>, std::size_t)) {
- for (std::size_t i = 0; i < 512; i++) {
- 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);
- ::on_all_pages(*os::paging::get_base_address(PML4T.contents[i]), f, virt_address);
- }
-}
-
void os::paging::load_pml4t(phys_ptr<PML4T> PML4T) {
asm volatile("mov %0, %%cr3" :: "r" (PML4T.get_phys_addr()) : "memory");
}
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.");
}
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>> phys_addr, decltype(paging_entry<depth>::page) page_info);
-
-// 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<0>*, phys_ptr<page<0>>, std::size_t));
+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);
+template <std::size_t depth>
+void on_all_pages(const paging_table<depth>& paging_table, auto f, std::size_t vaddr_offset = 0);
void load_pml4t(phys_ptr<PML4T> 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>> phys_addr, 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, decltype(paging_entry<depth>::page) 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], phys_addr);
+ set_page_base_address(paging_table.contents[index], paddr);
invlpg(vaddr);
} else {
if (paging_table.contents[index].non_page.P == 1) {
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()});
}
- map_page<depth, paging_depth - 1>(*get_base_address(paging_table.contents[index]), vaddr, phys_addr, page_info);
+ map_page<depth, paging_depth - 1>(*get_base_address(paging_table.contents[index]), vaddr, paddr, page_info);
+ }
+}
+
+template <std::size_t depth>
+void on_all_pages(const paging_table<depth>& paging_table, auto f, std::size_t vaddr_offset) {
+ for (std::size_t i = 0; i < 512; i++) {
+ if (!is_present(paging_table.contents[i])) {
+ continue;
+ }
+ std::size_t const new_offset = ([&]() {
+ std::size_t const new_offset = vaddr_offset + (i << (12 + 9 * depth));
+ return new_offset | (new_offset >> 47 ? 0xFFFF'8000'0000'0000 : 0);
+ })();
+ if constexpr (depth == 3) {
+ on_all_pages(*get_base_address(paging_table.contents[i]), f, new_offset);
+ } else if constexpr (depth == 0) {
+ f((page<depth>*)(new_offset), get_page_base_address(paging_table.contents[i]));
+ } else if (is_page(paging_table.contents[i])) {
+ f((page<depth>*)(new_offset), get_page_base_address(paging_table.contents[i]));
+ } else {
+ on_all_pages(*get_base_address(paging_table.contents[i]), f, new_offset);
+ }
}
}