From: Amelia Coutard <eliottulio.coutard@gmail.com>
Date: Thu, 13 Oct 2022 14:47:08 +0000 (+0200)
Subject: Made ftl_to_userspace jump to a loaded module at linear address 0x1000, instead of... 
X-Git-Url: https://git.ameliathe1st.gay/?a=commitdiff_plain;h=aab73ccaa51c082e412aeaf66a4bfe5091494da7;p=voyage-au-centre-des-fichiers.git

Made ftl_to_userspace jump to a loaded module at linear address 0x1000, instead of a function in the higher-half
---

diff --git a/grub.cfg b/grub.cfg
index 8eccea2..11f6906 100644
--- a/grub.cfg
+++ b/grub.cfg
@@ -1,3 +1,4 @@
 menuentry "Amycros" {
 	multiboot2 /boot/kernel.elf64
+	module2 /boot/test-module test-module
 }
diff --git a/src/boot.S b/src/boot.S
index fe2f52f..cd329af 100644
--- a/src/boot.S
+++ b/src/boot.S
@@ -17,6 +17,11 @@ multiboot_header_start:
 	.int 0
 	.int 0
 	.int 32
+	/* Modules alignment tag: */
+	.align 8
+	.short 6
+	.short 0
+	.int 8
 	/* End tag: */
 	.align 8
 	.short 0
diff --git a/src/kernel.cpp b/src/kernel.cpp
index 76d5167..c48b654 100644
--- a/src/kernel.cpp
+++ b/src/kernel.cpp
@@ -20,6 +20,10 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 		}
 	}
 
+	struct {
+		os::phys_ptr<os::paging::page> start_address = nullptr;
+		os::phys_ptr<os::paging::page> end_address = nullptr;
+	} test_module;
 	{
 		struct {
 			os::phys_ptr<os::paging::page> start_address = nullptr;
@@ -45,17 +49,27 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 					}
 				}
 				break;
+			case multiboot2::info::type_t::modules:
+				os::print(multiboot2::modules_mod_start(it) / 0x1000 * 0x1000);
+				os::print("->");
+				os::print(multiboot2::modules_mod_end(it) / 0x1000 * 0x1000);
+				os::print(": ");
+				os::print(multiboot2::modules_string(it));
+				os::printc('\n');
+				test_module.start_address = os::phys_ptr<os::paging::page>(multiboot2::modules_mod_start(it) / 0x1000 * 0x1000);
+				test_module.end_address   = os::phys_ptr<os::paging::page>(multiboot2::modules_mod_end(it)   / 0x1000 * 0x1000); // [s,e], not [s,e[
+				break;
 			default: break;
 			}
 		}
 
 		// kernel_start and kernel_end are aligned to 4K by the linker script.
-		const os::phys_ptr<os::paging::page> s = ([]() {
+		const os::phys_ptr<os::paging::page> kernel_s = ([]() {
 			os::phys_ptr<os::paging::page> ptr = nullptr;
 			asm("mov $_kernel_phys_start,%0" : "=ri"(ptr));
 			return ptr;
 		})();
-		const os::phys_ptr<os::paging::page> e = ([]() {
+		const os::phys_ptr<os::paging::page> kernel_e = ([]() {
 			os::phys_ptr<os::paging::page> ptr = nullptr;
 			asm("mov $_kernel_phys_end,%0" : "=ri"(ptr));
 			return ptr - 1; // [s, e], not [s, e[
@@ -63,20 +77,41 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 
 		// Remove kernel from available RAM:
 		for (std::size_t i = 0; i < available_ram_length; i++) {
-			if (e < available_ram[i].start_address || available_ram[i].end_address < s) {
+			if (kernel_e < available_ram[i].start_address || available_ram[i].end_address < kernel_s) {
 				continue;
 			}
-			if (s <= available_ram[i].start_address && available_ram[i].end_address <= e) {
+			if (kernel_s <= available_ram[i].start_address && available_ram[i].end_address <= kernel_e) {
 				available_ram[i] = available_ram[--available_ram_length];
-			} else if (s <= available_ram[i].start_address) {
-				available_ram[i].start_address = e + 1; // Since e < end_address, new start_address <= end_address.
-			} else if (available_ram[i].end_address <= e) {
-				available_ram[i].end_address = s - 1; // Since start_address < s, start_address <= new end_address.
+				i--;
+			} else if (kernel_s <= available_ram[i].start_address) {
+				available_ram[i].start_address = kernel_e + 1; // Since e < end_address, new start_address <= end_address.
+			} else if (available_ram[i].end_address <= kernel_e) {
+				available_ram[i].end_address = kernel_s - 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 = s - 1;
-				available_ram[available_ram_length].start_address = e + 1;
+				available_ram[i].end_address = kernel_s - 1;
+				available_ram[available_ram_length].start_address = kernel_e + 1;
+				available_ram_length++;
+			}
+		}
+		// Remove module from available RAM:
+		for (std::size_t i = 0; i < available_ram_length; i++) {
+			if (test_module.end_address < available_ram[i].start_address || available_ram[i].end_address < test_module.start_address) {
+				continue;
+			}
+			if (test_module.start_address <= available_ram[i].start_address && available_ram[i].end_address <= test_module.end_address) {
+				available_ram[i] = available_ram[--available_ram_length];
+				i--;
+			} else if (test_module.start_address <= available_ram[i].start_address) {
+				available_ram[i].start_address = test_module.end_address + 1; // Since e < end_address, new start_address <= end_address.
+			} else if (available_ram[i].end_address <= test_module.end_address) {
+				available_ram[i].end_address = test_module.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.start_address - 1;
+				available_ram[available_ram_length].start_address = test_module.end_address + 1;
 				available_ram_length++;
 			}
 		}
@@ -133,9 +168,37 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 		os::enable_interrupts(isr_info, idt);
 	}
 
-	get_base_address(PML4T.contents[0])->contents[0].page.P = false;
-	get_base_address(PML4T.contents[0])->contents[1].page.P = false;
+	// Unmap low RAM, and free corresponding page.
 	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);
+	}
+	asm volatile("invlpg (%0)" ::"r" (0x1000) : "memory");
+
+	os::paging::on_all_pages(PML4T, [](os::paging::page* virt, os::phys_ptr<os::paging::page> phys, std::size_t size) {
+		if (std::uint64_t(virt) >= 0xFFFF'8000'0000'0000) {
+			return;
+		}
+		os::print(std::uint64_t(virt));
+		os::print("->");
+		os::print(std::uint64_t(phys.get_phys_addr()));
+		os::print(" (");
+		os::print(size);
+		os::print(")\n");
+	});
 
 	// Allow userspaaaaaaaaace in ring 3. Otherwise, we just immediately page fault.
 	// Will make it a module soon-ish.
@@ -152,13 +215,3 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 	os::print("Trying move to ring 3:\n");
 	os::ftl_to_userspace();
 }
-
-extern "C" std::uint64_t syscall(std::uint64_t in1);
-
-extern "C" void userspaaaaaaaaace() {
-	syscall('a');
-	syscall('b');
-	syscall('c');
-	syscall('\n');
-	while (true) { asm volatile("nop"); }
-}
diff --git a/src/multiboot2.hpp b/src/multiboot2.hpp
index 9fd7c12..1428e5e 100644
--- a/src/multiboot2.hpp
+++ b/src/multiboot2.hpp
@@ -108,6 +108,16 @@
 	inline std::uint32_t memory_map_type(os::phys_ptr<const info> ptr, std::size_t index) {
 		return *reinterpret_cast<const std::uint32_t*>(&ptr->rest[8 + memory_map_entry_size(ptr) * index + 16]);
 	}
+
+	inline std::uint32_t modules_mod_start(os::phys_ptr<const info> ptr) {
+		return *reinterpret_cast<const std::uint32_t*>(&ptr->rest[0]);
+	}
+	inline std::uint32_t modules_mod_end(os::phys_ptr<const info> ptr) {
+		return *reinterpret_cast<const std::uint32_t*>(&ptr->rest[4]);
+	}
+	inline const char* modules_string(os::phys_ptr<const info> ptr) {
+		return reinterpret_cast<const char*>(&ptr->rest[8]);
+	}
 #endif // __cplusplus
 
 #ifdef __cplusplus
diff --git a/src/ring3.S b/src/ring3.S
index 3e21c2e..48bf822 100644
--- a/src/ring3.S
+++ b/src/ring3.S
@@ -2,7 +2,7 @@
 
 .globl ftl_to_userspace
 ftl_to_userspace:
-	mov $userspaaaaaaaaace, %rcx
+	mov $0x1000, %rcx
 	mov $0x202, %r11 # EFLAGS
 	sysretq
 
@@ -19,9 +19,3 @@ load_tss:
 	mov $GDT.TSS, %ax
 	ltr %ax
 	ret
-
-.globl syscall
-syscall:
-	mov %rcx, %r10
-	syscall
-	ret