.size = sizeof(bootstrap_pages_for_memory) / sizeof(bootstrap_pages_for_memory[0])
});
- // Allocate this page so that I only ever need to update the mapping once when I create a new process or port.
+ // Allocate those pages so that I only ever need to update the mapping once when I create a new process or port.
+ // TODO: Not an emergency, but adapt in case we need multiple PML4Es. (*NOT* the case right now.)
+ static_assert(sizeof(os::processes) > 1024 * 1024 * 1024, "Error: processes array too big.");
{
- const auto index = os::paging::calc_page_table_indices((void*)0xFFFF'C000'0000'0000).pml4e;
+ const auto index = os::paging::calc_page_table_indices(&os::processes).pml4e;
PML4T.contents[index] = {.P = 1, .R_W = 1, .U_S = 0, .PWT = 0, .PCD = 0, .base_address = 0, .NX = 0};
const auto PDPT_alloc = os::paging::page_allocator.allocate(1);
os::memset((void*)PDPT_alloc.ptr, 0, 0x1000);
set_base_address(PML4T.contents[index], os::phys_ptr<os::paging::PDPT>(PDPT_alloc.ptr.get_phys_addr()));
}
+ os::paging::setup_page(PML4T, (void*)0xFFFF'C000'0000'0000, 1, 0); // The startup module.
+ std::int64_t module_process = os::processes.create();
+
{
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.
-
bool module_specified = false;
for (auto it = multiboot2::next(info); it->type != multiboot2::info::type_t::end; it = multiboot2::next(it)) {
switch (it->type) {
os::print("{}->{}: {}\n", multiboot2::modules_mod_start(it), multiboot2::modules_mod_end(it), multiboot2::modules_string(it));
os::assert(!module_specified, "Multiple modules specified in the multiboot. This is unsupported.");
module_specified = true;
- os::elf::load_elf(os::get_process(0),
+ os::elf::load_elf(os::get_process(module_process),
(std::byte*)multiboot2::modules_mod_start(it),
multiboot2::modules_mod_end(it) - multiboot2::modules_mod_start(it),
PML4T);
os::enable_syscalls();
os::print("Moving to ring 3.\n");
- os::run_first_process();
+ os::run_first_process(module_process);
}
#include "serial.hpp"
#include "paging.hpp"
-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::run_first_process(std::int64_t pid) {
+ current_pid = pid;
+ os::paging::load_pml4t(os::get_process(current_pid).PML4T);
+ os::ftl_to_userspace((void*)os::get_process(current_pid).rip, (std::byte*)os::get_process(current_pid).rsp);
}
void os::set_ring0_stack(os::tss& tss, std::uint64_t stack) {
os::assert(false, "Incorrect %rax for syscall.");
}
-os::process& os::get_process(std::uint64_t pid) {
- os::assert(pid < 2048, "Invalid pid: {}.\n", pid);
- return ((process*)0xFFFF'C000'0000'0000)[pid];
+os::incrementing_int64_map<os::process>& os::processes = *reinterpret_cast<os::incrementing_int64_map<os::process>*>(0xFFFF'C000'0000'0000);
+std::int64_t os::current_pid;
+os::process& os::get_process(std::int64_t pid) {
+ return processes.get(pid);
}
-std::uint64_t os::current_pid;
struct process;
extern "C" void ftl_to_userspace(void* program, std::byte* stack);
-void run_first_process();
+void run_first_process(std::int64_t pid);
extern "C" void load_tss();
extern "C" void syscall_64bit_handler();
struct port {
bool exists;
- std::uint64_t : 0;
bool is_open;
std::uint64_t other_pid;
std::uint64_t other_port;
};
struct process {
- phys_ptr<paging::PML4T> PML4T;
+ phys_ptr<paging::PML4T> PML4T = nullptr;
std::uint64_t rax;
std::uint64_t rbx;
std::uint64_t rcx;
std::uint64_t r14;
std::uint64_t r15;
std::uint64_t rip;
- port ports[2043];
+ incrementing_int64_map<port> ports;
+ // char test[65536];
};
-static_assert(0xFFFF'C000'0000'0000 + sizeof(process) * 2048 < 0xFFFF'FFFF'8000'0000);
-extern "C" process& get_process(std::uint64_t pid);
+static_assert(0xFFFF'C000'0000'0000 + sizeof(incrementing_int64_map<process>) < 0xFFFF'FFFF'8000'0000);
-inline bool process_exists(std::uint64_t pid) {
- return pid < 2048;
-}
-inline bool port_exists(std::uint64_t pid, std::uint64_t port) {
- return port < 2043 && process_exists(pid) && get_process(pid).ports[port].exists;
-}
-
-extern "C" std::uint64_t current_pid;
+extern incrementing_int64_map<process>& processes;
+extern "C" std::int64_t current_pid;
+extern "C" process& get_process(std::int64_t pid);
} // namespace os
void os::set_msr(std::uint32_t msr, std::uint64_t v) {
asm volatile ("wrmsr" : : "a"(v & 0xFFFFFFFF), "d"((v >> 32) & 0xFFFFFFFF), "c"(msr));
}
+extern "C" void* os::memset(void* dest, int c, size_t n) {
+ while (n-- > 0) {
+ reinterpret_cast<std::byte*>(dest)[n] = std::byte(c);
+ }
+ return dest;
+}
+extern "C" void* os::memcpy(void* dest, const void* src, size_t n) {
+ while (n-- > 0) {
+ reinterpret_cast<std::byte*>(dest)[n] = reinterpret_cast<const std::byte*>(src)[n];
+ }
+ return dest;
+}
#include <cstdint>
#include <cstddef>
+#include <new>
+#include "serial.hpp"
namespace os {
template <typename T> T clamp(T min, T v, T max) {
return v < min ? min : max < v ? max : v;
}
-inline void* memset(void* dest, int c, size_t n) {
- while (n-- > 0) {
- reinterpret_cast<std::byte*>(dest)[n] = std::byte(c);
+extern "C" void* memset(void* dest, int c, size_t n);
+extern "C" void* memcpy(void* dest, const void* src, size_t n);
+
+template <typename T>
+struct incrementing_int64_map {
+public:
+ incrementing_int64_map() {}
+ incrementing_int64_map(const incrementing_int64_map& other) = delete;
+ incrementing_int64_map& operator=(const incrementing_int64_map& other) = delete;
+ ~incrementing_int64_map() {
+ for (std::int64_t i = 0; i < n; i++) {
+ if (present(i)) { remove(i); }
+ }
}
- return dest;
-}
-inline void* memcpy(void* dest, const void* src, size_t n) {
- while (n-- > 0) {
- reinterpret_cast<std::byte*>(dest)[n] = reinterpret_cast<const std::byte*>(src)[n];
+
+ bool has_room() {
+ return n < max_n;
}
- return dest;
-}
+ bool present(std::int64_t index) {
+ return 0 <= index && index < n && elems[index].present;
+ }
+ std::int64_t create() {
+ os::assert(has_room(), "Too many allocated elems in incrementing_int64_map.");
+ elems[n].present = true;
+ new(elems[n].buffer) T;
+ return n++;
+ }
+ void remove(std::int64_t index) {
+ os::assert(present(index), "Tried removing non-existant element of incrementing_int64_map.");
+ get(index).~T();
+ elems[index].present = false;
+ }
+ T& get(std::int64_t index) {
+ os::assert(present(index), "Tried getting non-existant element of incrementing_int64_map.");
+ return *reinterpret_cast<T*>(&elems[index].buffer[0]);
+ }
+ const T& get(std::int64_t index) const {
+ os::assert(present(index), "Tried getting non-existant element of incrementing_int64_map.");
+ return *reinterpret_cast<T*>(&elems[index].buffer[0]);
+ }
+
+private:
+ struct elem_t {
+ bool present;
+ alignas(T) std::byte buffer[sizeof(T)];
+ };
+ std::int64_t n = 0;
+ static constexpr std::int64_t max_n = 4096;
+ elem_t elems[max_n];
+};
} // namespace os