From 89697fc878f44965b2247252f91445eed77fd2be Mon Sep 17 00:00:00 2001
From: Amelia Coutard <eliottulio.coutard@gmail.com>
Date: Sat, 9 Dec 2023 02:22:12 +0100
Subject: [PATCH] Added basic structure to get ready for making a new, clean,
 PML4T right after boot

---
 kernel/linker.ld          |  2 ++
 kernel/src/boot.S         |  3 ++-
 kernel/src/interrupts.cpp |  3 +--
 kernel/src/kernel.cpp     | 22 +++++++++++++---------
 kernel/src/paging.cpp     |  4 +++-
 kernel/src/paging.hpp     |  2 ++
 6 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/kernel/linker.ld b/kernel/linker.ld
index b99ff70..b3fa2b6 100644
--- a/kernel/linker.ld
+++ b/kernel/linker.ld
@@ -44,6 +44,8 @@ SECTIONS {
 	.eh_frame ALIGN(4K) : AT(ADDR(.eh_frame) - KERNEL_VMA) {
 		*(.eh_frame)
 	}
+	. = ALIGN(4K);
+	_kernel_rw_start = . - KERNEL_VMA;
 	.data ALIGN(4K) : AT(ADDR(.data) - KERNEL_VMA) {
 		*(.data)
 		*(.data*)
diff --git a/kernel/src/boot.S b/kernel/src/boot.S
index 11a650a..f9adf20 100644
--- a/kernel/src/boot.S
+++ b/kernel/src/boot.S
@@ -111,7 +111,8 @@ IO_MAP:
 IO_MAP_END:
 
 .align 0x1000
-.globl PML4T
+.globl old_PML4T
+old_PML4T:
 PML4T: .quad PDPT_low - KERNEL_VMA + 3
        .skip 0x1000 - 16
        .quad PDPT_high - KERNEL_VMA + 3
diff --git a/kernel/src/interrupts.cpp b/kernel/src/interrupts.cpp
index 4e584fb..477431f 100644
--- a/kernel/src/interrupts.cpp
+++ b/kernel/src/interrupts.cpp
@@ -106,13 +106,12 @@ extern "C" void int_general_protection_fault(std::uint32_t err_code) {
 	os::print("Err code: {}.\n", err_code);
 	while (true) { os::hlt(); }
 }
-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'1000'0000) // process/port info
 	) { // Kernel memory
 		os::print("Allocating (Ring 0): {}\n", (void*)vaddr);
-		os::paging::setup_page(PML4T, (void*)vaddr, true, false);
+		os::paging::setup_page(os::paging::global_PML4T, (void*)vaddr, true, false);
 		return;
 	} else if (
 		(0x0000'7FFF'FFFF'0000 <= vaddr && vaddr < 0x0000'8000'0000'0000) // stack
diff --git a/kernel/src/kernel.cpp b/kernel/src/kernel.cpp
index beddfac..5093a0d 100644
--- a/kernel/src/kernel.cpp
+++ b/kernel/src/kernel.cpp
@@ -22,13 +22,19 @@
 os::idt<32> idt;
 extern "C" os::tss TSS;
 extern "C" char interrupt_stack_top;
-extern "C" os::paging::PML4T PML4T;
+extern "C" os::paging::PML4T old_PML4T;
 
 os::paging::page<0> 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.");
+	// TODO: Initialise new PML4T
+	os::paging::global_PML4T = old_PML4T;
+	// /TODO
+	os::print("a\n");
+	os::paging::load_pml4t(os::phys_ptr<os::paging::PML4T>{std::uintptr_t(&os::paging::global_PML4T) - 0xFFFF'FFFF'8000'0000});
+	os::print("b\n");
 
 	if (!os::init_serial_port()) {
 		while (true) {
@@ -86,10 +92,10 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 	static_assert(sizeof(os::processes) <= 1024 * 1024 * 1024, "Error: processes array too big.");
 	{
 		const auto index = os::paging::calc_page_table_indices(&os::processes).pml4e;
-		PML4T.contents[index] = {.non_page = {.P = 1, .R_W = 1, .U_S = 0, .PWT = 0, .PCD = 0, .base_address = 0, .NX = 0}};
+		os::paging::global_PML4T.contents[index] = {.non_page = {.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()));
+		set_base_address(os::paging::global_PML4T.contents[index], os::phys_ptr<os::paging::PDPT>(PDPT_alloc.ptr.get_phys_addr()));
 	}
 
 	{
@@ -109,6 +115,7 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 				);
 				break;
 			case multiboot2::info::type_t::memory_map:
+				os::print("RAM:\n");
 				for (std::size_t i = 0; i < multiboot2::memory_map_number_of_entries(it); i++) {
 					if (multiboot2::memory_map_type(it, i) == 1) {
 						// Rounded up, to avoid including non-ram.
@@ -120,9 +127,11 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 						if (s <= e) { // In the case where no full page is included in the ram section, don't add it.
 							os::assert(available_ram_length < 50, "Too much available RAM sections to initialise correctly. Will fix eventually, probably.");
 							available_ram[available_ram_length++] = {.start_address = s, .end_address = e};
+							os::print("{} -> {} ({})\n", s, e + 1, (unsigned long)(e + 1 - s));
 						}
 					}
 				}
+				os::print("RAM END\n");
 				break;
 			case multiboot2::info::type_t::modules:
 				os::print("{}->{}: {}\n", multiboot2::modules_mod_start(it), multiboot2::modules_mod_end(it), multiboot2::modules_string(it));
@@ -130,7 +139,7 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 				os::elf::load_elf(os::get_process(os::processes.create()),
 				                  (std::byte*)multiboot2::modules_mod_start(it),
 				                  multiboot2::modules_mod_end(it) - multiboot2::modules_mod_start(it),
-				                  PML4T);
+				                  os::paging::global_PML4T);
 				break;
 			default: break;
 			}
@@ -184,11 +193,6 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 	os::paging::page_allocator.print_all();
 	os::print("RAM END\n");
 
-	// Unmap low RAM, and free corresponding page.
-	PML4T.contents[0].non_page.P = false;
-	os::paging::page_allocator.deallocate({.ptr = os::phys_ptr<os::paging::page<0>>(get_base_address(PML4T.contents[0]).get_phys_addr()), .size = 1});
-	os::invlpg((void*)0x0);
-
 	os::print("Loading ring 3 interrupts stack.\n");
 	os::set_ring0_stack(TSS, std::uint64_t(&interrupt_stack_top));
 	os::print("Loading TSS.\n");
diff --git a/kernel/src/paging.cpp b/kernel/src/paging.cpp
index 532b306..2d44735 100644
--- a/kernel/src/paging.cpp
+++ b/kernel/src/paging.cpp
@@ -14,6 +14,8 @@
 #include "paging.hpp"
 #include "serial.hpp"
 
+os::paging::PML4T os::paging::global_PML4T;
+
 std::byte* os::paging::setup_page(os::paging::PML4T& PML4T, const void* vaddr, bool R_W, bool U_S) {
 	const auto indices = os::paging::calc_page_table_indices(vaddr);
 	if (PML4T.contents[indices.pml4e].non_page.P == 0) {
@@ -105,7 +107,7 @@ void os::paging::on_all_pages(const os::paging::PML4T& PML4T, void f(page<0>*, p
 }
 
 void os::paging::load_pml4t(phys_ptr<PML4T> PML4T) {
-	asm volatile("mov %0, %%cr3" :: "r" (PML4T.get_phys_addr() | 0x10) : "memory"); // 0x10 disables the cache.
+	asm volatile("mov %0, %%cr3" :: "r" (PML4T.get_phys_addr()) : "memory");
 }
 
 os::paging::page_allocator_t os::paging::page_allocator{};
diff --git a/kernel/src/paging.hpp b/kernel/src/paging.hpp
index 6955a7b..eb1696f 100644
--- a/kernel/src/paging.hpp
+++ b/kernel/src/paging.hpp
@@ -41,6 +41,8 @@ static_assert(sizeof(page<0>) == 0x1000);
 static_assert(sizeof(page<1>) == 0x1000 * 512);
 static_assert(sizeof(page<2>) == 0x1000ull * 512 * 512);
 
+extern PML4T global_PML4T;
+
 template<> struct paging_entry<3> {
 	struct {
 		std::uint64_t P : 1 = 0;
-- 
2.46.0