PML4T.contents[0].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.print_all();
- // Map test_module to virtual address 0x0000'0000'0000'1000.
- {
- os::phys_ptr<os::paging::PT> PT {os::paging::page_allocator.allocate(1).ptr.get_phys_addr()};
- os::phys_ptr<os::paging::PDT> PDT {os::paging::page_allocator.allocate(1).ptr.get_phys_addr()};
- os::phys_ptr<os::paging::PDPT> PDPT{os::paging::page_allocator.allocate(1).ptr.get_phys_addr()};
- PML4T.contents[0] = { .P = 1, .R_W = 0, .U_S = 1, .PWT = 0, .PCD = 0, .base_address = 0, .NX = 0};
- PDPT->contents[0] = {.non_page = {.P = 1, .R_W = 0, .U_S = 1, .PWT = 0, .PCD = 0, .base_address = 0, .NX = 0}};
- PDT->contents[0] = {.non_page = {.P = 1, .R_W = 0, .U_S = 1, .PWT = 0, .PCD = 0, .base_address = 0, .NX = 0}};
- PT->contents[1] = { .P = 1, .R_W = 0, .U_S = 1, .PWT = 0, .PCD = 0, .PAT = 0, .G = 0, .base_address = 0, .NX = 0};
- set_base_address(PML4T.contents[0], PDPT);
- set_base_address(PDPT->contents[0], PDT);
- set_base_address(PDT->contents[0], PT);
- set_page_base_address(PT->contents[1], test_module.start_address);
+ // Load test-module elf file:
+ const os::elf::header elf_header = *os::phys_ptr<os::elf::header>(test_module.start_address.get_phys_addr());
+
+ // Check if elf is valid:
+ os::assert(elf_header.magic[0] == '\x7f', "No elf header.");
+ os::assert(elf_header.magic[1] == 'E', "No elf header.");
+ os::assert(elf_header.magic[2] == 'L', "No elf header.");
+ os::assert(elf_header.magic[3] == 'F', "No elf header.");
+ os::assert(elf_header.bitn == 2, "Elf file not 64 bits.");
+ os::assert(elf_header.endianness == 1, "Elf file not little endian.");
+ os::assert(elf_header.type == 2, "Elf file not executable.");
+ os::assert(elf_header.arch == 0x3E, "Elf file not x86_64.");
+
+ for (std::size_t i = 0; i < elf_header.entry_count_program_header_table; i++) {
+ const os::elf::program_header program_header = *os::phys_ptr<os::elf::program_header>(
+ (os::phys_ptr<std::byte>(test_module.start_address.get_phys_addr()) + elf_header.program_header_table
+ + i * elf_header.entry_size_program_header_table).get_phys_addr()
+ );
+ if (program_header.type != 1) { // Segment shouldn't be loaded.
+ os::print("Segment.\n");
+ continue;
+ }
+ os::print("Segment: loadable\n");
+ os::assert((std::uintptr_t(program_header.p_vaddr) & 0xFFF) == 0, "Program segment not 4KiB aligned.");
+
+ // Allocate memory for segment:
+ std::size_t nb_pages = (program_header.p_memsz + 1023) / 1024;
+ for (std::size_t i = 0; i < nb_pages; i++) {
+ const auto indices = os::paging::calc_page_table_indices(program_header.p_vaddr + 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 = 0, .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 = 0, .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 = 0, .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 = 0, .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 memory for segment:
+ for (std::size_t i = 0; i < program_header.p_filesz; i++) {
+ program_header.p_vaddr[i] = os::phys_ptr<std::byte>(test_module.start_address.get_phys_addr())[program_header.p_offset + i];
+ }
+ for (std::size_t i = program_header.p_filesz; i < program_header.p_memsz; i++) {
+ program_header.p_vaddr[i] = std::byte(0);
+ }
}
asm volatile("invlpg (%0)" ::"r" (0x1000) : "memory");
os::print("{}->{} ({})\n", std::uint64_t(virt), std::uint64_t(phys.get_phys_addr()), size);
});
- // Allow userspaaaaaaaaace in ring 3. Otherwise, we just immediately page fault.
+ // 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;
os::print("Enabling syscalls.\n");
os::enable_syscalls();
os::print("Moving to ring 3.\n");
- os::ftl_to_userspace();
+ os::ftl_to_userspace(elf_header.entry);
}