:: commit 67a0bb8749277759a3d1a7a7b49c39bdadc03945

Andy-Python-Programmer <andypythonappdeveloper@gmail.com> — 2022-01-27 04:01

parents: 360b23eb2b

paging: emulate support for 1gib pages if not avaliable

Signed-off-by: Andy-Python-Programmer <andypythonappdeveloper@gmail.com>
diff --git a/stage23/mm/vmm.c b/stage23/mm/vmm.c
index d16233c8..2f99193a 100644
--- a/stage23/mm/vmm.c
+++ b/stage23/mm/vmm.c
@@ -39,6 +39,24 @@ pagemap_t new_pagemap(int lv) {
     return pagemap;
 }
 
+static bool is_1gib_page_supported() {
+    // Cache the cpuid result :^)
+    static bool CACHE_INIT = false;
+    static bool CACHE = false;
+
+    if (!CACHE_INIT) {
+        // Check if 1GiB pages are supported:
+        uint32_t eax, ebx, ecx, edx;
+
+        CACHE = cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx) && ((edx & 1 << 26) == 1 << 26);
+        CACHE_INIT = true;
+
+        print("paging: 1GiB pages are %s!\n", CACHE ? "supported" : "not supported");
+    }
+
+    return CACHE;
+}
+
 void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags, enum page_size pg_size) {
     // Calculate the indices in the various tables using the virtual address
     size_t pml5_entry = (virt_addr & ((uint64_t)0x1ff << 48)) >> 48;
@@ -67,8 +85,17 @@ level4:
     pml3 = get_next_level(pml4, pml4_entry);
 
     if (pg_size == Size1GiB) {
-        pml3[pml3_entry] = (pt_entry_t)(phys_addr | flags | (1 << 7));
-        return;
+        // Check if 1GiB pages are avaliable.
+        if (is_1gib_page_supported()) {
+            pml3[pml3_entry] = (pt_entry_t)(phys_addr | flags | (1 << 7));
+            return;
+        } else {
+            // If 1GiB pages are not supported then emulate it by splitting them into
+            // 2MiB pages.
+            for (uint64_t i = 0; i < 0x40000000; i += 0x200000) {
+                map_page(pagemap, virt_addr + i, phys_addr + i, flags, Size2MiB);
+            }
+        }
     }
 
     pml2 = get_next_level(pml3, pml3_entry);
tab: 248 wrap: offon