0000'7FFF'FFFF'0000 ↔ 0000'8000'0000'0000 - stack: 64KiB
-- Invalid addresses --
FFFF'8000'0000'0000 ↔ FFFF'C000'0000'0000 - physical memory: 64TiB
-FFFF'C000'0000'0000 ↔ FFFF'C000'0001'0000 - process information table: 64KiB, 2048 processes at most
-FFFF'C000'0001'0000 ↔ FFFF'C000'0801'0000 - port information table: 128MiB, 4096 ports per process at most
-FFFF'C000'0801'0000 ↔ FFFF'FFFF'8000'0000 - unmapped: 64TiB - 2GiB - 128MiB - 64KiB
+FFFF'C000'0000'0000 ↔ FFFF'C000'1000'0000 - process information table: 256MiB, 2048 processes, 4093 ports/process
+FFFF'C000'1000'0000 ↔ FFFF'FFFF'8000'0000 - unmapped: 64TiB - 2GiB - 128MiB - 64KiB
FFFF'FFFF'8000'0000 ↔10000'0000'0000'0000 - kernel: 2GiB
---------------------------
#include "elf64.hpp"
-os::process os::elf::load_elf(std::byte* start, std::size_t length, const paging::PML4T& original_PML4T) {
+void os::elf::load_elf(os::process& result, std::byte* start, std::size_t length, const paging::PML4T& original_PML4T) {
os::assert(length >= sizeof(os::elf::header), "Elf file isn't big enough to contain a header: there is an error.");
// TODO: Check that the elf file sections are all fully inside the file.
constexpr std::size_t stack_size = 16 * 0x1000 /* 64KiB */;
std::byte* const stack = (std::byte*)0x0000'8000'0000'0000 - stack_size;
- os::process result = {
- .PML4T = phys_ptr<paging::PML4T>(os::paging::page_allocator.allocate(1).ptr.get_phys_addr()),
- .rip = std::uint64_t(elf_header.entry),
- .rsp = std::uint64_t(stack + stack_size)
- };
+
+ result.exists = true;
+ result.PML4T = phys_ptr<paging::PML4T>(os::paging::page_allocator.allocate(1).ptr.get_phys_addr());
+ result.rip = std::uint64_t(elf_header.entry);
+ result.rsp = std::uint64_t(stack + stack_size);
+ result.rbx = 0;
+ result.rbp = 0;
+ result.r12 = 0;
+ result.r13 = 0;
+ result.r14 = 0;
+ result.r15 = 0;
+ result.mxcsr = 0;
+ result.x87cw = 0;
// Copy kernel mappings to the new virtual address space.
memset(result.PML4T->contents, 0, 256 * sizeof(os::paging::PML4E));
memcpy(page, start + program_header.p_offset, clamp(0ul, program_header.p_filesz - i * 0x1000, 0x1000ul));
}
}
-
- return result;
}
};
static_assert(sizeof(program_header) == 56);
- process load_elf(std::byte* start, std::size_t length, const paging::PML4T& original_PML4T);
+ void load_elf(os::process& result, std::byte* start, std::size_t length, const paging::PML4T& original_PML4T);
} } // namespace os::elf
extern "C" os::paging::PML4T PML4T;
extern "C" void int_page_fault(std::uint32_t err_code, std::uint64_t vaddr) {
if (
- (0xFFFF'C000'0000'0000 <= vaddr && vaddr < 0xFFFF'C000'0801'0000) // process/port info
+ (0xFFFF'C000'0000'0000 <= vaddr && vaddr < 0xFFFF'C000'1000'0000) // process/port info
) { // Kernel memory
os::print("Allocating (Ring 0): {}\n", (void*)vaddr);
os::paging::setup_page(PML4T, (void*)vaddr, true, false);
set_base_address(PML4T.contents[index], os::phys_ptr<os::paging::PDPT>(PDPT_alloc.ptr.get_phys_addr()));
}
- os::process test_module_process = { nullptr, 0, 0 };
{
struct {
os::phys_ptr<os::paging::page> start_address = nullptr;
} available_ram[50];
std::size_t available_ram_length = 0;
+ os::paging::setup_page(PML4T, (void*)0xFFFF'C000'0000'0000, 1, 0); // The startup module.
+
for (auto it = multiboot2::next(info); it->type != multiboot2::info::type_t::end; it = multiboot2::next(it)) {
switch (it->type) {
case multiboot2::info::type_t::memory_map:
break;
case multiboot2::info::type_t::modules:
os::print("{}->{}: {}\n", multiboot2::modules_mod_start(it), multiboot2::modules_mod_end(it), multiboot2::modules_string(it));
- os::assert(test_module_process.PML4T == nullptr, "Multiple modules specified in the multiboot. This is unsupported.");
- test_module_process =
- os::elf::load_elf((std::byte*)multiboot2::modules_mod_start(it),
- multiboot2::modules_mod_end(it) - multiboot2::modules_mod_start(it),
- PML4T);
+ os::assert(!os::get_process(0).exists, "Multiple modules specified in the multiboot. This is unsupported.");
+ os::elf::load_elf(os::get_process(0),
+ (std::byte*)multiboot2::modules_mod_start(it),
+ multiboot2::modules_mod_end(it) - multiboot2::modules_mod_start(it),
+ PML4T);
break;
default: break;
}
}
- os::assert(test_module_process.PML4T != nullptr, "No modules specified in the multiboot. This is unsupported.");
+ os::assert(os::get_process(0).exists, "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::enable_syscalls();
os::print("Moving to ring 3.\n");
- os::run_first_process(test_module_process);
+ os::run_first_process();
}
#include "serial.hpp"
#include "paging.hpp"
-void os::run_first_process(os::process& process) {
- os::current_pid = 1;
- os::get_process(os::current_pid) = process;
- os::paging::load_pml4t(process.PML4T);
- os::ftl_to_userspace((void*)process.rip, (std::byte*)process.rsp);
+void os::run_first_process() {
+ os::current_pid = 0;
+ os::paging::load_pml4t(os::get_process(0).PML4T);
+ os::ftl_to_userspace((void*)os::get_process(0).rip, (std::byte*)os::get_process(0).rsp);
}
void os::set_ring0_stack(os::tss& tss, std::uint64_t stack) {
struct process;
extern "C" void ftl_to_userspace(void* program, std::byte* stack);
-void run_first_process(process& process);
+void run_first_process();
extern "C" void load_tss();
extern "C" void syscall_64bit_handler();
void set_ring0_stack(tss& tss, std::uint64_t stack);
void enable_syscalls();
+struct port {
+ bool exists;
+ std::uint64_t : 0;
+ bool is_open;
+ std::uint64_t other_pid;
+ std::uint64_t other_port;
+};
+
struct process {
+ bool exists;
phys_ptr<paging::PML4T> PML4T;
std::uint64_t rip;
+ std::uint64_t rbx;
std::uint64_t rsp;
- std::uint64_t : 64;
+ std::uint64_t rbp;
+ std::uint64_t r12;
+ std::uint64_t r13;
+ std::uint64_t r14;
+ std::uint64_t r15;
+ std::uint64_t mxcsr;
+ std::uint64_t x87cw;
+ port ports[4093];
};
-static_assert(sizeof(process) == 32);
-
-// (¬0);0 -> port was closed on other side, via syscall or program termination
-// 0 ;0 -> port doesn't exist
-struct port {
- std::uint64_t other_pid;
- std::uint64_t other_port;
-};
-static_assert(sizeof(port) == 16);
+static_assert(sizeof(process) == 0x1000 * 32);
inline process& get_process(std::uint64_t pid) {
- os::assert(1 <= pid && pid <= 2048, "Invalid pid: {}.\n", pid);
- return ((process*)0xFFFF'C000'0000'0000)[pid - 1];
+ os::assert(pid < 2048, "Invalid pid: {}.\n", pid);
+ return ((process*)0xFFFF'C000'0000'0000)[pid];
}
inline bool process_exists(std::uint64_t pid) {
- return 1 <= pid && pid <= 2048 && get_process(pid).rsp != 0;
-}
-inline port& get_port(std::uint64_t pid, std::uint64_t port) {
- os::assert(1 <= pid && pid <= 2048, "Invalid pid: {}.\n", pid);
- os::assert(1 <= port && port <= 4096, "Invalid port: {}.\n", pid);
- return ((os::port*)0xFFFF'C000'0001'0000)[(pid - 1) * 4096 + (port - 1)];
+ return pid < 2048 && get_process(pid).exists;
}
inline bool port_exists(std::uint64_t pid, std::uint64_t port) {
- return process_exists(pid) && 1 <= port && port <= 4096 && get_port(pid, port).other_pid != 0;
+ return port < 4093 && process_exists(pid) && get_process(pid).ports[port].exists;
}
extern std::uint64_t current_pid;