:: commit 1ccf8e34bca0eed85319ac5065d236d1e8860faf

mintsuki <mintsuki@protonmail.com> — 2020-09-11 12:09

parents: 0c7e08d3c7

Adapt new vmm to 5-level paging as well

diff --git a/src/mm/vmm64.c b/src/mm/vmm64.c
index 78e0ad4b..644a59b4 100644
--- a/src/mm/vmm64.c
+++ b/src/mm/vmm64.c
@@ -23,19 +23,35 @@ static pt_entry_t *get_next_level(pt_entry_t *current_level, size_t entry) {
     return ret;
 }
 
-pagemap_t new_pagemap(void) {
-    return (pagemap_t)(size_t)balloc_aligned(PT_SIZE, PT_SIZE);
+pagemap_t new_pagemap(int lv) {
+    pagemap_t pagemap;
+    pagemap.levels    = lv;
+    pagemap.top_level = balloc_aligned(PT_SIZE, PT_SIZE);
+    return pagemap;
 }
 
 void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags) {
     // Calculate the indices in the various tables using the virtual address
+    size_t pml5_entry = (virt_addr & ((uint64_t)0x1ff << 48)) >> 48;
     size_t pml4_entry = (virt_addr & ((uint64_t)0x1ff << 39)) >> 39;
     size_t pml3_entry = (virt_addr & ((uint64_t)0x1ff << 30)) >> 30;
     size_t pml2_entry = (virt_addr & ((uint64_t)0x1ff << 21)) >> 21;
 
-    pt_entry_t *pml4 = (pt_entry_t *)(size_t)pagemap;
-    pt_entry_t *pml3 = get_next_level(pml4, pml4_entry);
-    pt_entry_t *pml2 = get_next_level(pml3, pml3_entry);
+    pt_entry_t *pml5, *pml4, *pml3, *pml2;
+
+    // Paging levels
+    switch (pagemap.levels) {
+        case 5:
+            pml5 = pagemap.top_level;
+            pml4 = get_next_level(pml5, pml5_entry);
+            break;
+        case 4:
+            pml4 = pagemap.top_level;
+            break;
+    }
+
+    pml3 = get_next_level(pml4, pml4_entry);
+    pml2 = get_next_level(pml3, pml3_entry);
 
     // Set the entry as present and point it to the passed physical address
     // Also set the specified flags
diff --git a/src/mm/vmm64.h b/src/mm/vmm64.h
index 7e63f58e..a42511fc 100644
--- a/src/mm/vmm64.h
+++ b/src/mm/vmm64.h
@@ -5,9 +5,12 @@
 
 #define PAGE_SIZE ((uint64_t)0x200000)
 
-typedef uint64_t pagemap_t;
+typedef struct {
+    int   levels;
+    void *top_level;
+} pagemap_t;
 
-pagemap_t new_pagemap(void);
+pagemap_t new_pagemap(int lv);
 void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags);
 
 #endif
diff --git a/src/protos/stivale.c b/src/protos/stivale.c
index beb8461e..b0583ff8 100644
--- a/src/protos/stivale.c
+++ b/src/protos/stivale.c
@@ -262,7 +262,6 @@ __attribute__((noreturn)) void stivale_spinup(int bits, bool level5pg,
     pic_flush();
 
     if (bits == 64) {
-        void *pagemap_ptr;
         if (level5pg) {
             // Enable CR4.LA57
             ASM(
@@ -270,55 +269,19 @@ __attribute__((noreturn)) void stivale_spinup(int bits, bool level5pg,
                 "bts eax, 12\n\t"
                 "mov cr4, eax\n\t", :: "eax", "memory"
             );
+        }
 
-            struct pagemap {
-                uint64_t pml5[512];
-                uint64_t pml4_lo[512];
-                uint64_t pml4_hi[512];
-                uint64_t pml3_lo[512];
-                uint64_t pml3_hi[512];
-                uint64_t pml2_0gb[512];
-                uint64_t pml2_1gb[512];
-                uint64_t pml2_2gb[512];
-                uint64_t pml2_3gb[512];
-            };
-            struct pagemap *pagemap = balloc_aligned(sizeof(struct pagemap), 0x1000);
-            pagemap_ptr = (void *)pagemap;
-
-            // zero out the pagemap
-            for (uint64_t *p = (uint64_t *)pagemap; p < &pagemap->pml3_hi[512]; p++)
-                *p = 0;
-
-            pagemap->pml5[511]    = (uint64_t)(size_t)pagemap->pml4_hi  | 0x03;
-            pagemap->pml5[0]      = (uint64_t)(size_t)pagemap->pml4_lo  | 0x03;
-            pagemap->pml4_hi[511] = (uint64_t)(size_t)pagemap->pml3_hi  | 0x03;
-            pagemap->pml4_hi[256] = (uint64_t)(size_t)pagemap->pml3_lo  | 0x03;
-            pagemap->pml4_lo[0]   = (uint64_t)(size_t)pagemap->pml3_lo  | 0x03;
-            pagemap->pml3_hi[510] = (uint64_t)(size_t)pagemap->pml2_0gb | 0x03;
-            pagemap->pml3_hi[511] = (uint64_t)(size_t)pagemap->pml2_1gb | 0x03;
-            pagemap->pml3_lo[0]   = (uint64_t)(size_t)pagemap->pml2_0gb | 0x03;
-            pagemap->pml3_lo[1]   = (uint64_t)(size_t)pagemap->pml2_1gb | 0x03;
-            pagemap->pml3_lo[2]   = (uint64_t)(size_t)pagemap->pml2_2gb | 0x03;
-            pagemap->pml3_lo[3]   = (uint64_t)(size_t)pagemap->pml2_3gb | 0x03;
-
-            // populate the page directories
-            for (size_t i = 0; i < 512 * 4; i++)
-                (&pagemap->pml2_0gb[0])[i] = (i * 0x200000) | 0x03 | (1 << 7);
-        } else {
-            pagemap_t pagemap = new_pagemap();
-
-            // Map 0 to 2GiB at 0xffffffff80000000
-            for (uint64_t i = 0; i < 0x80000000; i += PAGE_SIZE) {
-                map_page(pagemap, i + 0xffffffff80000000, i, 0x03);
-            }
+        pagemap_t pagemap = new_pagemap(level5pg ? 5 : 4);
 
-            // Map 0 to 4GiB at 0xffff800000000000 and 0
-            for (uint64_t i = 0; i < 0x100000000; i += PAGE_SIZE) {
-                map_page(pagemap, i, i, 0x03);
-                map_page(pagemap, i + 0xffff800000000000, i, 0x03);
-            }
+        // Map 0 to 2GiB at 0xffffffff80000000
+        for (uint64_t i = 0; i < 0x80000000; i += PAGE_SIZE) {
+            map_page(pagemap, i + 0xffffffff80000000, i, 0x03);
+        }
 
-            pagemap_ptr = (void *)pagemap;
+        // Map 0 to 4GiB at 0xffff800000000000 and 0
+        for (uint64_t i = 0; i < 0x100000000; i += PAGE_SIZE) {
+            map_page(pagemap, i, i, 0x03);
+            map_page(pagemap, i + 0xffff800000000000, i, 0x03);
         }
 
         ASM(
@@ -367,7 +330,7 @@ __attribute__((noreturn)) void stivale_spinup(int bits, bool level5pg,
 
             "iretq\n\t"
             ".code32\n\t",
-            : "a" (pagemap_ptr), "b" (&entry_point),
+            : "a" (pagemap.top_level), "b" (&entry_point),
               "D" (stivale_struct), "S" (&stack)
             : "memory"
         );
diff --git a/test/test.asm b/test/test.asm
index 0d2aff6a..1596b2a3 100644
--- a/test/test.asm
+++ b/test/test.asm
@@ -7,7 +7,13 @@ stivale_header:
     dq 0         ; entry point
     dq stack.top ; rsp
     dq 0         ; flags
-    dq 0         ; tags
+    dq lv5         ; tags
+
+section .rodata
+
+lv5:
+    dq 0x932f477032007e8f
+    dq 0
 
 section .bss
 
tab: 248 wrap: offon