From c0a96aa7e4de7f4987fb58123b4fd0e0f769f93b Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jackpot51@gmail.com>
Date: Tue, 15 Feb 2022 08:53:53 -0700
Subject: [PATCH] Reduce memory used by x86_64 page tables

---
 src/arch/x86_64/paging.rs | 45 +++++++++++++++++++--------------------
 src/main.rs               |  2 +-
 2 files changed, 23 insertions(+), 24 deletions(-)

diff --git a/src/arch/x86_64/paging.rs b/src/arch/x86_64/paging.rs
index 5715cd0..847485a 100644
--- a/src/arch/x86_64/paging.rs
+++ b/src/arch/x86_64/paging.rs
@@ -23,13 +23,10 @@ pub unsafe fn paging_create<
     D: Disk,
     M: Iterator<Item=OsMemoryEntry>,
     V: Iterator<Item=OsVideoMode>
->(os: &mut dyn Os<D, M, V>, kernel_phys: usize) -> Option<usize> {
+>(os: &mut dyn Os<D, M, V>, kernel_phys: usize, kernel_size: usize) -> Option<usize> {
     // Create PML4
     let pml4 = paging_allocate(os)?;
 
-    // Recursive mapping for compatibility
-    pml4[511] = pml4.as_ptr() as u64 | 1 << 1 | 1;
-
     {
         // Create PDP for identity mapping
         let pdp = paging_allocate(os)?;
@@ -38,20 +35,15 @@ pub unsafe fn paging_create<
         pml4[0] = pdp.as_ptr() as u64 | 1 << 1 | 1;
         pml4[256] = pdp.as_ptr() as u64 | 1 << 1 | 1;
 
-        // Identity map 8 GiB pages
+        // Identity map 8 GiB using 2 MiB pages
         for pdp_i in 0..8 {
             let pd = paging_allocate(os)?;
             pdp[pdp_i] = pd.as_ptr() as u64 | 1 << 1 | 1;
             for pd_i in 0..pd.len() {
-                let pt = paging_allocate(os)?;
-                pd[pd_i] = pt.as_ptr() as u64 | 1 << 1 | 1;
-                for pt_i in 0..pt.len() {
-                    let addr =
-                        pdp_i as u64 * 0x4000_0000 +
-                        pd_i as u64 * 0x20_0000 +
-                        pt_i as u64 * 0x1000;
-                    pt[pt_i] = addr | 1 << 1 | 1;
-                }
+                let addr =
+                    pdp_i as u64 * 0x4000_0000 +
+                    pd_i as u64 * 0x20_0000;
+                pd[pd_i] = addr | 1 << 7 | 1 << 1 | 1;
             }
         }
     }
@@ -63,23 +55,30 @@ pub unsafe fn paging_create<
         // Link second to last PML4 entry to PDP
         pml4[510] = pdp.as_ptr() as u64 | 1 << 1 | 1;
 
-        // Map 1 GiB at kernel offset
-        for pdp_i in 0..1 {
+        // Map kernel_size at kernel offset
+        let mut kernel_mapped = 0;
+        let mut pdp_i = 0;
+        while kernel_mapped < kernel_size && pdp_i < pdp.len() {
             let pd = paging_allocate(os)?;
             pdp[pdp_i] = pd.as_ptr() as u64 | 1 << 1 | 1;
-            for pd_i in 0..pd.len() {
+            pdp_i += 1;
+
+            let mut pd_i = 0;
+            while kernel_mapped < kernel_size && pd_i < pd.len(){
                 let pt = paging_allocate(os)?;
                 pd[pd_i] = pt.as_ptr() as u64 | 1 << 1 | 1;
-                for pt_i in 0..pt.len() {
-                    let addr =
-                        pdp_i as u64 * 0x4000_0000 +
-                        pd_i as u64 * 0x20_0000 +
-                        pt_i as u64 * 0x1000 +
-                        kernel_phys as u64;
+                pd_i += 1;
+
+                let mut pt_i = 0;
+                while kernel_mapped < kernel_size && pt_i < pt.len() {
+                    let addr = (kernel_phys + kernel_mapped) as u64;
                     pt[pt_i] = addr | 1 << 1 | 1;
+                    pt_i += 1;
+                    kernel_mapped += 4096;
                 }
             }
         }
+        assert!(kernel_mapped >= kernel_size);
     }
 
     Some(pml4.as_ptr() as usize)
diff --git a/src/main.rs b/src/main.rs
index f7ef087..557ecbe 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -291,7 +291,7 @@ fn main<
         kernel
     };
 
-    let page_phys = unsafe { paging_create(os, kernel.as_ptr() as usize) }
+    let page_phys = unsafe { paging_create(os, kernel.as_ptr() as usize, kernel.len()) }
         .expect("Failed to set up paging");
     //TODO: properly reserve page table allocations so kernel does not re-use them
 
-- 
GitLab