:: commit d9466f3d250084ea4e01e93d7c5f092934a64098

mintsuki <mintsuki@protonmail.com> — 2021-04-14 19:57

parents: 5488c8818b

stivale2: Implement unmap NULL using 4KiB pages

diff --git a/stage23/mm/vmm.c b/stage23/mm/vmm.c
index 46c59eb6..ef681d50 100644
--- a/stage23/mm/vmm.c
+++ b/stage23/mm/vmm.c
@@ -31,14 +31,15 @@ pagemap_t new_pagemap(int lv) {
     return pagemap;
 }
 
-void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags) {
+void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags, bool hugepages) {
     // 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;
+    size_t pml1_entry = (virt_addr & ((uint64_t)0x1ff << 12)) >> 12;
 
-    pt_entry_t *pml5, *pml4, *pml3, *pml2;
+    pt_entry_t *pml5, *pml4, *pml3, *pml2, *pml1;
 
     // Paging levels
     switch (pagemap.levels) {
@@ -58,8 +59,12 @@ level4:
     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
-    // We only use 2MiB pages else we would not have enough space
-    pml2[pml2_entry] = (pt_entry_t)(phys_addr | flags | (1 << 7));
+    if (hugepages) {
+        pml2[pml2_entry] = (pt_entry_t)(phys_addr | flags | (1 << 7));
+        return;
+    }
+
+    pml1 = get_next_level(pml2, pml2_entry);
+
+    pml1[pml1_entry] = (pt_entry_t)(phys_addr | flags | (1 << 7));
 }
diff --git a/stage23/mm/vmm.h b/stage23/mm/vmm.h
index fe265903..9aa096c5 100644
--- a/stage23/mm/vmm.h
+++ b/stage23/mm/vmm.h
@@ -2,8 +2,7 @@
 #define __MM__VMM_H__
 
 #include <stdint.h>
-
-#define PAGE_SIZE ((uint64_t)0x200000)
+#include <stdbool.h>
 
 typedef struct {
     int   levels;
@@ -11,6 +10,6 @@ typedef struct {
 } pagemap_t;
 
 pagemap_t new_pagemap(int lv);
-void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags);
+void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags, bool hugepages);
 
 #endif
diff --git a/stage23/protos/stivale.c b/stage23/protos/stivale.c
index 5f910ea6..a9d055a2 100644
--- a/stage23/protos/stivale.c
+++ b/stage23/protos/stivale.c
@@ -218,15 +218,21 @@ pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null) {
     uint64_t higher_half_base = level5pg ? 0xff00000000000000 : 0xffff800000000000;
 
     // Map 0 to 2GiB at 0xffffffff80000000
-    for (uint64_t i = 0; i < 0x80000000; i += PAGE_SIZE) {
-        map_page(pagemap, 0xffffffff80000000 + i, i, 0x03);
+    for (uint64_t i = 0; i < 0x80000000; i += 0x200000) {
+        map_page(pagemap, 0xffffffff80000000 + i, i, 0x03, true);
     }
 
-    // Map 0 to 4GiB at higher half base and 0
-    for (uint64_t i = 0; i < 0x100000000; i += PAGE_SIZE) {
+    // Sub 2MiB mappings
+    for (uint64_t i = 0; i < 0x200000; i += 0x1000) {
         if (!(i == 0 && unmap_null))
-            map_page(pagemap, i, i, 0x03);
-        map_page(pagemap, higher_half_base + i, i, 0x03);
+            map_page(pagemap, i, i, 0x03, false);
+        map_page(pagemap, higher_half_base + i, i, 0x03, false);
+    }
+
+    // Map 2MiB to 4GiB at higher half base and 0
+    for (uint64_t i = 0x200000; i < 0x100000000; i += 0x200000) {
+        map_page(pagemap, i, i, 0x03, true);
+        map_page(pagemap, higher_half_base + i, i, 0x03, true);
     }
 
     size_t _memmap_entries = memmap_entries;
@@ -247,14 +253,14 @@ pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null) {
         if (base >= top)
             continue;
 
-        uint64_t aligned_base   = ALIGN_DOWN(base, PAGE_SIZE);
-        uint64_t aligned_top    = ALIGN_UP(top, PAGE_SIZE);
+        uint64_t aligned_base   = ALIGN_DOWN(base, 0x200000);
+        uint64_t aligned_top    = ALIGN_UP(top, 0x200000);
         uint64_t aligned_length = aligned_top - aligned_base;
 
-        for (uint64_t i = 0; i < aligned_length; i += PAGE_SIZE) {
+        for (uint64_t i = 0; i < aligned_length; i += 0x200000) {
             uint64_t page = aligned_base + i;
-            map_page(pagemap, page, page, 0x03);
-            map_page(pagemap, higher_half_base + page, page, 0x03);
+            map_page(pagemap, page, page, 0x03, true);
+            map_page(pagemap, higher_half_base + page, page, 0x03, true);
         }
     }
 
diff --git a/test/stivale2.c b/test/stivale2.c
index b51c0a35..e196eecd 100644
--- a/test/stivale2.c
+++ b/test/stivale2.c
@@ -23,15 +23,15 @@ struct stivale2_header_tag_smp smp_request = {
     .flags = 0
 };
 
-struct stivale2_tag fb_mtrr_request = {
-    .identifier = STIVALE2_HEADER_TAG_FB_MTRR_ID,
+struct stivale2_tag unmap_null_request = {
+    .identifier = STIVALE2_HEADER_TAG_UNMAP_NULL_ID,
     .next       = (uint64_t)&smp_request
 };
 
 struct stivale2_header_tag_framebuffer framebuffer_request = {
     .tag = {
         .identifier = STIVALE2_HEADER_TAG_FRAMEBUFFER_ID,
-        .next       = (uint64_t)&fb_mtrr_request
+        .next       = (uint64_t)&unmap_null_request
     },
     .framebuffer_width  = 0,
     .framebuffer_height = 0,
tab: 248 wrap: offon