extern "C" char interrupt_stack_top;
extern "C" os::paging::PML4T PML4T;
-os::paging::page bootstrap_pages_for_memory[32]; // 32 pages = 128 KiB
+os::paging::page<0> bootstrap_pages_for_memory[32]; // 32 pages = 128 KiB
extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_start> info) {
os::assert(magic == 0x36D76289, "Incorrect magic number: wasn't booted with multiboot2.");
}
os::paging::page_allocator.deallocate({
- .ptr = os::phys_ptr<os::paging::page>(reinterpret_cast<uintptr_t>(bootstrap_pages_for_memory) - 0xFFFF'FFFF'8000'0000),
+ .ptr = os::phys_ptr<os::paging::page<0>>(reinterpret_cast<uintptr_t>(bootstrap_pages_for_memory) - 0xFFFF'FFFF'8000'0000),
.size = sizeof(bootstrap_pages_for_memory) / sizeof(bootstrap_pages_for_memory[0])
});
{
struct {
- os::phys_ptr<os::paging::page> start_address = nullptr;
- os::phys_ptr<os::paging::page> end_address = nullptr;
+ os::phys_ptr<os::paging::page<0>> start_address = nullptr;
+ os::phys_ptr<os::paging::page<0>> end_address = nullptr;
} available_ram[50];
std::size_t available_ram_length = 0;
for (std::size_t i = 0; i < multiboot2::memory_map_number_of_entries(it); i++) {
if (multiboot2::memory_map_type(it, i) == 1) {
// Rounded up, to avoid including non-ram.
- const os::phys_ptr<os::paging::page>
+ const os::phys_ptr<os::paging::page<0>>
s{(multiboot2::memory_map_base_addr(it, i) + 0x1000 - 1) / 0x1000 * 0x1000};
// Rounded down, to avoid including non-ram.
- const os::phys_ptr<os::paging::page>
+ const os::phys_ptr<os::paging::page<0>>
e{(multiboot2::memory_map_base_addr(it, i) + multiboot2::memory_map_length(it, i)) / 0x1000 * 0x1000 - 0x1000};
if (s <= e) { // In the case where no full page is included in the ram section, don't add it.
os::assert(available_ram_length < 50, "Too much available RAM sections to initialise correctly. Will fix eventually, probably.");
os::assert(module_specified, "No modules specified in the multiboot. This is unsupported.");
// kernel_start and kernel_end are aligned to 4K by the linker script.
- const os::phys_ptr<os::paging::page> kernel_s = ([]() {
- os::phys_ptr<os::paging::page> ptr = nullptr;
+ const os::phys_ptr<os::paging::page<0>> kernel_s = ([]() {
+ os::phys_ptr<os::paging::page<0>> ptr = nullptr;
asm("mov $_kernel_phys_start,%0" : "=ri"(ptr));
return ptr;
})();
- const os::phys_ptr<os::paging::page> kernel_e = ([]() {
- os::phys_ptr<os::paging::page> ptr = nullptr;
+ const os::phys_ptr<os::paging::page<0>> kernel_e = ([]() {
+ os::phys_ptr<os::paging::page<0>> ptr = nullptr;
asm("mov $_kernel_phys_end,%0" : "=ri"(ptr));
return ptr - 1; // [s, e], not [s, e[
})();
// Unmap low RAM, and free corresponding page.
PML4T.contents[0].non_page.P = false;
- os::paging::page_allocator.deallocate({.ptr = os::phys_ptr<os::paging::page>(get_base_address(PML4T.contents[0]).get_phys_addr()), .size = 1});
+ os::paging::page_allocator.deallocate({.ptr = os::phys_ptr<os::paging::page<0>>(get_base_address(PML4T.contents[0]).get_phys_addr()), .size = 1});
os::invlpg((void*)0x0);
os::print("Loading ring 3 interrupts stack.\n");
{.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()));
+ set_page_base_address(PT.contents[indices.pe], os::phys_ptr<os::paging::page<0>>(page_alloc.ptr.get_phys_addr()));
invlpg(vaddr);
return (std::byte*)&*page_alloc.ptr;
}
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) {
+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*>(virt_address), os::paging::get_page_base_address(PT.contents[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*, os::phys_ptr<os::paging::page>, std::size_t), std::size_t PDT_virt_address) {
+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*>(virt_address), os::paging::get_page_base_address(PDT.contents[i]), 0x1000ull * 512ull);
+ 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*, os::phys_ptr<os::paging::page>, std::size_t), std::size_t PDPT_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*>(virt_address), os::paging::get_page_base_address(PDPT.contents[i]), 0x1000ull * 512ull * 512ull);
+ 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*, phys_ptr<page>, std::size_t)) {
+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;
return { .ptr = nullptr, .size = count };
}
if (begin->size == count) {
- block result = { .ptr = phys_ptr<paging::page>{begin.get_phys_addr()}, .size = count };
+ block result = { .ptr = phys_ptr<paging::page<0>>{begin.get_phys_addr()}, .size = count };
begin = begin->next;
return result;
}
for (phys_ptr<page> it = begin; it != nullptr; it = it->next) {
if (it->size == count) {
prec->next = it->next;
- return { .ptr = phys_ptr<paging::page>{it.get_phys_addr()}, .size = count };
+ return { .ptr = phys_ptr<paging::page<0>>{it.get_phys_addr()}, .size = count };
}
if (it->size > count) {
it->size -= count;
- return { .ptr = phys_ptr<paging::page>{it.get_phys_addr()} + it->size, .size = count };
+ return { .ptr = phys_ptr<paging::page<0>>{it.get_phys_addr()} + it->size, .size = count };
}
prec = it;
}
template <std::size_t depth> struct __attribute__((aligned(0x1000))) paging_table {
paging_entry<depth> contents[512];
};
-template <> struct __attribute__((aligned(0x1000))) paging_table<0> {
- std::byte contents[4096];
-};
-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>;
+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);
-template<> struct paging_entry<4> {
+template<> struct paging_entry<3> {
struct {
std::uint64_t P : 1 = 0;
std::uint64_t R_W : 1;
std::uint64_t NX : 1;
} non_page;
};
-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);
+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<3> {
+template<> struct paging_entry<2> {
union {
struct {
std::uint64_t P : 1 = 0;
} 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);
+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<2> {
+template <> struct paging_entry<1> {
union {
struct {
std::uint64_t P : 1 = 0;
} 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);
+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<1> {
+template <> struct paging_entry<0> {
struct {
std::uint64_t P : 1 = 0;
std::uint64_t R_W : 1;
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);
+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);
inline bool is_page(const PML4E __attribute__((unused))& PML4E) { return false; }
os::assert(!is_page(PDE), "Tried to get non-page out of a page paging.");
return phys_ptr<PT>{PDE.non_page.base_address * 0x1000ull};
}
-inline phys_ptr<page> get_page_base_address(const PDPE& PDPE) {
+inline phys_ptr<page<2>> 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<page>{PDPE.page.base_address * 0x1000ull * 512ull * 512ull};
+ return phys_ptr<page<2>>{PDPE.page.base_address * sizeof(page<2>)};
}
-inline phys_ptr<page> get_page_base_address(const PDE& PDE) {
+inline phys_ptr<page<1>> 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<page>{PDE.page.base_address * 0x1000ull * 512ull};
+ return phys_ptr<page<1>>{PDE.page.base_address * sizeof(page<1>)};
}
-inline phys_ptr<page> get_page_base_address(const PE& PE) {
+inline phys_ptr<page<0>> 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.page.base_address * 0x1000ull};
+ return phys_ptr<page<0>>{PE.page.base_address * sizeof(page<0>)};
}
inline void set_base_address(PML4E& PML4E, phys_ptr<PDPT> 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<page> ptr) {
+inline void set_page_base_address(PDPE& PDPE, phys_ptr<page<2>> 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;
+ PDPE.page.base_address = ptr.get_phys_addr() / sizeof(*ptr);
}
-inline void set_page_base_address(PDE& PDE, phys_ptr<page> ptr) {
+inline void set_page_base_address(PDE& PDE, phys_ptr<page<1>> 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;
+ PDE.page.base_address = ptr.get_phys_addr() / sizeof(*ptr);
}
-inline void set_page_base_address(PE& PE, phys_ptr<page> ptr) {
+inline void set_page_base_address(PE& PE, phys_ptr<page<0>> ptr) {
os::assert(is_page(PE), "Tried to get page out of a non-page paging.");
- PE.page.base_address = ptr.get_phys_addr() / 0x1000ull;
+ PE.page.base_address = ptr.get_phys_addr() / sizeof(*ptr);
}
struct page_table_indices {
std::byte* setup_page(PML4T& PML4T, const void* vaddr, bool R_W, bool U_S);
// 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<page>, std::size_t));
+void on_all_pages(const PML4T& PML4T, void f(page<0>*, phys_ptr<page<0>>, std::size_t));
void load_pml4t(phys_ptr<PML4T> PML4T);
class page_allocator_t {
public:
struct block {
- phys_ptr<paging::page> ptr = nullptr;
+ phys_ptr<paging::page<0>> ptr = nullptr;
std::uint64_t size;
};