program_header.p_vaddr[i] = std::byte(0);
}
}
+
+ // Allocate and map stack.
+ constexpr std::size_t stack_size = 16 * 0x1000 /* 64KiB */;
+ std::byte * const stack = (std::byte*)0x0000'8000'0000'0000 - stack_size;
+ for (std::size_t i = 0; i < stack_size / 0x1000 /* 64KiB */; i++) {
+ const auto indices = os::paging::calc_page_table_indices(stack + i * 0x1000);
+ os::assert(indices.pml4e < 256, "Userspace program must be in the lower-half of virtual memory.");
+ if (PML4T.contents[indices.pml4e].P == 0) {
+ PML4T.contents[indices.pml4e] = {.P = 1, .R_W = 1, .U_S = 1, .PWT = 0, .PCD = 0, .base_address = 0, .NX = 0};
+ const auto PDPT_alloc = os::paging::page_allocator.allocate(1);
+ set_base_address(PML4T.contents[indices.pml4e], os::phys_ptr<os::paging::PDPT>(PDPT_alloc.ptr.get_phys_addr()));
+ }
+ os::paging::PDPT& PDPT = *get_base_address(PML4T.contents[indices.pml4e]);
+ if (PDPT.contents[indices.pdpe].non_page.P == 0) {
+ PDPT.contents[indices.pdpe] = {.non_page = {.P = 1, .R_W = 1, .U_S = 1, .PWT = 0, .PCD = 0, .base_address = 0, .NX = 0}};
+ const auto PDT_alloc = os::paging::page_allocator.allocate(1);
+ set_base_address(PDPT.contents[indices.pdpe], os::phys_ptr<os::paging::PDT>(PDT_alloc.ptr.get_phys_addr()));
+ }
+ os::paging::PDT& PDT = *get_base_address(PDPT.contents[indices.pdpe]);
+ if (PDT.contents[indices.pde].non_page.P == 0) {
+ PDT.contents[indices.pde] = {.non_page = {.P = 1, .R_W = 1, .U_S = 1, .PWT = 0, .PCD = 0, .base_address = 0, .NX = 0}};
+ const auto PT_alloc = os::paging::page_allocator.allocate(1);
+ set_base_address(PDT.contents[indices.pde], os::phys_ptr<os::paging::PT>(PT_alloc.ptr.get_phys_addr()));
+ }
+ os::paging::PT& PT = *get_base_address(PDT.contents[indices.pde]);
+ if (PT.contents[indices.pe].P == 0) {
+ PT.contents[indices.pe] = {.P = 1, .R_W = 1, .U_S = 1, .PWT = 0, .PCD = 0, .PAT = 0, .G = 0, .base_address = 0, .NX = 0};
+ const auto page_alloc = os::paging::page_allocator.allocate(1);
+ set_page_base_address(PT.contents[indices.pe], os::phys_ptr<os::paging::page>(page_alloc.ptr.get_phys_addr()));
+ }
+ }
+
+ // Initialise stack to 0.
+ for (std::size_t i = 0; i < stack_size; i++) {
+ stack[i] = std::byte(0);
+ }
+
asm volatile("invlpg (%0)" ::"r" (0x1000) : "memory");
os::paging::on_all_pages(PML4T, [](os::paging::page* virt, os::phys_ptr<os::paging::page> phys, std::size_t size) {
os::print("{}->{} ({})\n", std::uint64_t(virt), std::uint64_t(phys.get_phys_addr()), size);
});
- // Allow kernel in ring 3. Otherwise, we just immediately page fault.
- // Will make it a module soon-ish.
- get_base_address(PML4T.contents[511])->contents[510].page.U_S = true;
- get_base_address(PML4T.contents[511])->contents[511].page.U_S = true;
- PML4T.contents[511].U_S = true;
-
os::print("Loading ring 3 interrupts stack.\n");
os::set_ring0_stack(TSS, std::uint64_t(&interrupt_stack_top));
os::print("Loading TSS.\n");
os::print("Enabling syscalls.\n");
os::enable_syscalls();
os::print("Moving to ring 3.\n");
- os::ftl_to_userspace(elf_header.entry);
+ os::ftl_to_userspace(elf_header.entry, stack + stack_size);
}