From 6a1c1ee62a2ef7eb5dd65aa331dcc54822fcf112 Mon Sep 17 00:00:00 2001
From: Amelia Coutard <eliottulio.coutard@gmail.com>
Date: Mon, 13 Mar 2023 15:14:51 +0100
Subject: [PATCH] Moved the loading of the elf program before the aquisition of
 most physical memory, in order to allow for freeing the corresponding
 multiboot module more easily

---
 kernel/src/kernel.cpp | 69 +++++++++++++++----------------------------
 1 file changed, 24 insertions(+), 45 deletions(-)

diff --git a/kernel/src/kernel.cpp b/kernel/src/kernel.cpp
index 2e4146e..244eb1c 100644
--- a/kernel/src/kernel.cpp
+++ b/kernel/src/kernel.cpp
@@ -24,6 +24,8 @@ extern "C" os::tss TSS;
 extern "C" char interrupt_stack_top;
 extern "C" os::paging::PML4T PML4T;
 
+os::paging::page bootstrap_pages_for_memory[32]; // 32 pages = 128 KiB
+
 extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_start> info) {
 	os::assert(magic == 0x36D76289, "Incorrect magic number: wasn't booted with multiboot2.");
 	os::assert(os::cpu_has_msr(), "MSRs aren't supported.");
@@ -34,10 +36,20 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 		}
 	}
 
-	struct {
-		std::uint64_t start_address = 0;
-		std::uint64_t end_address = 0;
-	} test_module;
+	os::paging::page_allocator.deallocate({
+		.ptr = os::phys_ptr<os::paging::page>(reinterpret_cast<uintptr_t>(bootstrap_pages_for_memory) - 0xFFFF'FFFF'8000'0000),
+		.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.
+	{
+		const auto index = os::paging::calc_page_table_indices((void*)0xFFFF'C000'0000'0000).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);
+		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;
@@ -65,13 +77,18 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 				break;
 			case multiboot2::info::type_t::modules:
 				os::print("{}->{}: {}\n", multiboot2::modules_mod_start(it) / 0x1000 * 0x1000, multiboot2::modules_mod_end(it) / 0x1000 * 0x1000, multiboot2::modules_string(it));
-				test_module.start_address = multiboot2::modules_mod_start(it);
-				test_module.end_address   = multiboot2::modules_mod_end(it);
+				os::assert(test_module_process.PML4T == nullptr, "Multiple modules specified in the multiboot. This is unsupported.");
+				test_module_process =
+					os::elf::load_elf(&*os::phys_ptr<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.");
+
 		// kernel_start and kernel_end are aligned to 4K by the linker script.
 		const os::phys_ptr<os::paging::page> kernel_s = ([]() {
 			os::phys_ptr<os::paging::page> ptr = nullptr;
@@ -104,35 +121,8 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 				available_ram_length++;
 			}
 		}
-		struct {
-			os::phys_ptr<os::paging::page> start_address;
-			os::phys_ptr<os::paging::page> end_address;
-		} test_module_block{
-			os::phys_ptr<os::paging::page>(test_module.start_address / 0x1000 * 0x1000),
-			os::phys_ptr<os::paging::page>(test_module.end_address / 0x1000 * 0x1000)
-		};
-		// Remove module from available RAM:
-		for (std::size_t i = 0; i < available_ram_length; i++) {
-			if (test_module_block.end_address < available_ram[i].start_address || available_ram[i].end_address < test_module_block.start_address) {
-				continue;
-			}
-			if (test_module_block.start_address <= available_ram[i].start_address && available_ram[i].end_address <= test_module_block.end_address) {
-				available_ram[i] = available_ram[--available_ram_length];
-				i--;
-			} else if (test_module_block.start_address <= available_ram[i].start_address) {
-				available_ram[i].start_address = test_module_block.end_address + 1; // Since e < end_address, new start_address <= end_address.
-			} else if (available_ram[i].end_address <= test_module_block.end_address) {
-				available_ram[i].end_address = test_module_block.start_address - 1; // Since start_address < s, start_address <= new end_address.
-			} else {
-				os::assert(available_ram_length < 50, "Too much available RAM sections to initialise correctly. Will fix eventually, probably.");
-				available_ram[available_ram_length] = available_ram[i];
-				available_ram[i].end_address = test_module_block.start_address - 1;
-				available_ram[available_ram_length].start_address = test_module_block.end_address + 1;
-				available_ram_length++;
-			}
-		}
 
-		// Add available RAM to the page allocator (warning: overrides the multiboot info structure):
+		// Add available RAM to the page allocator (warning: overrides the multiboot info structure and the multiboot modules):
 		for (std::size_t i = 0; i < available_ram_length; i++) {
 			os::paging::page_allocator.deallocate({
 				.ptr = available_ram[i].start_address,
@@ -186,17 +176,6 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 	os::paging::page_allocator.deallocate({.ptr = os::phys_ptr<os::paging::page>(get_base_address(PML4T.contents[0]).get_phys_addr()), .size = 1});
 	os::invlpg((void*)0x0);
 
-	// Allocate this page so that I only ever need to update the mapping once when I create a new process or port.
-	{
-		const auto index = os::paging::calc_page_table_indices((void*)0xFFFF'C000'0000'0000).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);
-		set_base_address(PML4T.contents[index], os::phys_ptr<os::paging::PDPT>(PDPT_alloc.ptr.get_phys_addr()));
-	}
-
-	auto test_module_process =
-		os::elf::load_elf(&*os::phys_ptr<std::byte>(test_module.start_address), test_module.end_address - test_module.start_address, PML4T);
-
 	os::print("Loading ring 3 interrupts stack.\n");
 	os::set_ring0_stack(TSS, std::uint64_t(&interrupt_stack_top));
 	os::print("Loading TSS.\n");
-- 
2.46.0