From: Amelia Coutard <eliottulio.coutard@gmail.com>
Date: Sat, 5 Aug 2023 00:22:22 +0000 (+0200)
Subject: Implemented ports and processes better.
X-Git-Url: https://git.ameliathe1st.gay/?a=commitdiff_plain;h=e5f2d11063104615c33edd32dc9e7bce5ca445b4;p=voyage-au-centre-des-fichiers.git

Implemented ports and processes better.
---

diff --git a/kernel/src/kernel.cpp b/kernel/src/kernel.cpp
index 2035138..5b70c4c 100644
--- a/kernel/src/kernel.cpp
+++ b/kernel/src/kernel.cpp
@@ -41,15 +41,20 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 		.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;
@@ -57,8 +62,6 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 		} 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) {
@@ -82,7 +85,7 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 				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);
@@ -192,5 +195,5 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 	os::enable_syscalls();
 
 	os::print("Moving to ring 3.\n");
-	os::run_first_process();
+	os::run_first_process(module_process);
 }
diff --git a/kernel/src/ring3.cpp b/kernel/src/ring3.cpp
index c8b8400..ddba192 100644
--- a/kernel/src/ring3.cpp
+++ b/kernel/src/ring3.cpp
@@ -16,10 +16,10 @@
 #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) {
@@ -69,8 +69,8 @@ extern "C" void os::syscall_rax_error_handler() {
 	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;
diff --git a/kernel/src/ring3.hpp b/kernel/src/ring3.hpp
index 32e17ed..252e7c1 100644
--- a/kernel/src/ring3.hpp
+++ b/kernel/src/ring3.hpp
@@ -40,7 +40,7 @@ struct __attribute__((packed)) tss {
 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();
 
@@ -54,14 +54,13 @@ 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 {
-	phys_ptr<paging::PML4T> PML4T;
+	phys_ptr<paging::PML4T> PML4T = nullptr;
 	std::uint64_t rax;
 	std::uint64_t rbx;
 	std::uint64_t rcx;
@@ -79,19 +78,14 @@ struct process {
 	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
diff --git a/kernel/src/utils.cpp b/kernel/src/utils.cpp
index 326de3b..d1b997b 100644
--- a/kernel/src/utils.cpp
+++ b/kernel/src/utils.cpp
@@ -50,3 +50,15 @@ std::uint64_t os::get_msr(std::uint32_t msr) {
 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;
+}
diff --git a/kernel/src/utils.hpp b/kernel/src/utils.hpp
index c203c80..95c4109 100644
--- a/kernel/src/utils.hpp
+++ b/kernel/src/utils.hpp
@@ -15,6 +15,8 @@
 
 #include <cstdint>
 #include <cstddef>
+#include <new>
+#include "serial.hpp"
 
 namespace os {
 
@@ -30,17 +32,55 @@ void set_msr(std::uint32_t msr, std::uint64_t v);
 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