From 28300182f2968467f1cfa98c7574ec89718bdf78 Mon Sep 17 00:00:00 2001
From: Amelia Coutard <eliottulio.coutard@gmail.com>
Date: Tue, 11 Oct 2022 08:38:45 +0200
Subject: [PATCH] Moved the GDT to the higher half (added a second lgdt after
 jump to 64 bits), to allow for unmapping the whole lower half

---
 src/boot.S     | 12 +++++++++++-
 src/kernel.cpp |  6 ++++--
 src/paging.cpp |  8 ++++----
 src/paging.hpp |  2 +-
 4 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/src/boot.S b/src/boot.S
index 9faf67a..d265748 100644
--- a/src/boot.S
+++ b/src/boot.S
@@ -188,11 +188,21 @@ _start:
 	mov %eax, %cr0
 
 	# Jump to 64 bits:
-	lgdt (GDT.PTR - KERNEL_VMA)
+	lgdt GDT.PTR - KERNEL_VMA
 	jmp $GDT.KERNEL_CODE, $.trampoline
 
 .code64
 .trampoline:
+	mov %esp, %esp
+
+	movq $GDT, GDT.PTR + 2
+	lgdt GDT.PTR # Reload GDT in higher half.
+	pushq $GDT.KERNEL_CODE
+	movabsq $.trampoline2, %rax
+	pushq %rax
+	lretq # Jump to new GDT.
+.trampoline2:
+
 	mov $GDT.KERNEL_DATA, %ax  # Set the A-register to the data descriptor.
 	mov %ax, %ds        # Set the data segment to the A-register.
 	mov %ax, %es        # Set the extra segment to the A-register.
diff --git a/src/kernel.cpp b/src/kernel.cpp
index a52ecab..baf2dc7 100644
--- a/src/kernel.cpp
+++ b/src/kernel.cpp
@@ -5,6 +5,7 @@
 #include "interrupts.hpp"
 
 os::idt<32> idt;
+extern "C" os::paging::PML4T PML4T;
 
 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.");
@@ -129,8 +130,9 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
 		os::enable_interrupts(isr_info, idt);
 	}
 
-	os::phys_ptr<os::paging::PML4T> PML4T = nullptr;
-	asm ("movq $PML4T - 0xFFFFFFFF80000000,%0" : "=ri"(PML4T) : );
+	PML4T.contents[0].base_address()->contents[0].P(false);
+	PML4T.contents[0].base_address()->contents[1].P(false);
+	PML4T.contents[0].P(false);
 	os::print("Mapping:\n");
 	os::paging::print_mapping(PML4T);
 
diff --git a/src/paging.cpp b/src/paging.cpp
index 9c2f133..7d0f9ff 100644
--- a/src/paging.cpp
+++ b/src/paging.cpp
@@ -3,9 +3,9 @@
 
 // void os::paging::unmap(phys_ptr<PML4T> PLM4T, page* virt, std::uint64_t length) { }
 // void os::paging::map(phys_ptr<PML4T> PLM4T, page* virt, std::uint64_t length, phys_ptr<page> phys) { }
-template<int order> void print_mapping(os::phys_ptr<os::paging::paging_table<order>> table, std::uint64_t virt_address, bool show_higher_half) {
+template<int order> void print_mapping(const os::paging::paging_table<order>& table, std::uint64_t virt_address, bool show_higher_half) {
 	for (std::size_t i = 0; i < (order == 3 && !show_higher_half ? 256 : 512); i++) {
-		const auto& page = table->contents[i];
+		const auto& page = table.contents[i];
 		if (!page.P()) { continue; }
 		std::uint64_t new_virt = virt_address + i * (4096ul << (order * 9));
 		new_virt |= ((new_virt & 0x0000800000000000) != 0 ? 0xFFFF000000000000 : 0);
@@ -18,12 +18,12 @@ template<int order> void print_mapping(os::phys_ptr<os::paging::paging_table<ord
 			os::print(")\n");
 		} else {
 			if constexpr (order > 0) { // Will never be false when !page.is_page().
-				print_mapping<order - 1>(page.base_address(), new_virt, show_higher_half);
+				print_mapping<order - 1>(*page.base_address(), new_virt, show_higher_half);
 			}
 		}
 	}
 }
-void os::paging::print_mapping(phys_ptr<PML4T> PML4T, bool show_higher_half) {
+void os::paging::print_mapping(const PML4T& PML4T, bool show_higher_half) {
 	::print_mapping(PML4T, 0, show_higher_half);
 }
 
diff --git a/src/paging.hpp b/src/paging.hpp
index 83a556f..347733b 100644
--- a/src/paging.hpp
+++ b/src/paging.hpp
@@ -152,7 +152,7 @@ using page = paging_table<-1>;
 
 void unmap(phys_ptr<PML4T> PLM4T, page* virt, std::uint64_t length);
 void map(phys_ptr<PML4T> PLM4T, page* virt, std::uint64_t length, phys_ptr<page> phys);
-void print_mapping(phys_ptr<PML4T> PML4T, bool show_higher_half = false);
+void print_mapping(const PML4T& PML4T, bool show_higher_half = false);
 
 class page_allocator_t;
 extern page_allocator_t page_allocator;
-- 
2.46.0