:: commit 1e60942ec92716acf83b0248dda50d560d468bfc

mintsuki <mintsuki@protonmail.com> — 2024-07-06 18:31

parents: 2c09275aab

protos/limine: Do not ignore MAX_PAGING_MODE config setting if paging mode request missing. Closes #380

diff --git a/common/mm/vmm.h b/common/mm/vmm.h
index c7023586..9c3eb2c2 100644
--- a/common/mm/vmm.h
+++ b/common/mm/vmm.h
@@ -15,6 +15,8 @@
 #define PAGING_MODE_X86_64_4LVL 0
 #define PAGING_MODE_X86_64_5LVL 1
 
+#define PAGING_MODE_MAX PAGING_MODE_X86_64_5LVL
+
 #define paging_mode_va_bits(mode) ((mode) ? 57 : 48)
 
 static inline uint64_t paging_mode_higher_half(int paging_mode) {
@@ -52,6 +54,8 @@ void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_
 #define PAGING_MODE_AARCH64_4LVL 0
 #define PAGING_MODE_AARCH64_5LVL 1
 
+#define PAGING_MODE_MAX PAGING_MODE_AARCH64_5LVL
+
 #define paging_mode_va_bits(mode) ((mode) ? 52 : 48)
 
 static inline uint64_t paging_mode_higher_half(int paging_mode) {
@@ -91,6 +95,8 @@ void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_
 #define PAGING_MODE_RISCV_SV48 9
 #define PAGING_MODE_RISCV_SV57 10
 
+#define PAGING_MODE_MAX PAGING_MODE_RISCV_SV57
+
 int paging_mode_va_bits(int paging_mode);
 
 enum page_size {
diff --git a/common/protos/limine.c b/common/protos/limine.c
index 473ab5ab..0005a32b 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -457,24 +457,63 @@ noreturn void limine_load(char *config, char *cmdline) {
     int paging_mode, max_supported_paging_mode;
 
 #if defined (__x86_64__) || defined (__i386__)
-    paging_mode = max_supported_paging_mode = PAGING_MODE_X86_64_4LVL;
+    max_supported_paging_mode = PAGING_MODE_X86_64_4LVL;
     if (cpuid(0x00000007, 0, &eax, &ebx, &ecx, &edx) && (ecx & (1 << 16))) {
         printv("limine: CPU has 5-level paging support\n");
         max_supported_paging_mode = PAGING_MODE_X86_64_5LVL;
     }
-
 #elif defined (__aarch64__)
-    paging_mode = max_supported_paging_mode = PAGING_MODE_AARCH64_4LVL;
+    max_supported_paging_mode = PAGING_MODE_AARCH64_4LVL;
     // TODO(qookie): aarch64 also has optional 5 level paging when using 4K pages
-
 #elif defined (__riscv64)
     max_supported_paging_mode = vmm_max_paging_mode();
-    paging_mode = max_supported_paging_mode >= PAGING_MODE_RISCV_SV48 ? PAGING_MODE_RISCV_SV48 : PAGING_MODE_RISCV_SV39;
-
+    max_supported_paging_mode >= PAGING_MODE_RISCV_SV48 ? PAGING_MODE_RISCV_SV48 : PAGING_MODE_RISCV_SV39;
 #else
 #error Unknown architecture
 #endif
 
+    int user_max_paging_mode = PAGING_MODE_MAX;
+
+    char *user_max_paging_mode_s = config_get_value(config, 0, "MAX_PAGING_MODE");
+    if (user_max_paging_mode_s != NULL) {
+#if defined (__x86_64__) || defined (__i386__)
+        if (strcasecmp(user_max_paging_mode_s, "4level") == 0) {
+            user_max_paging_mode = PAGING_MODE_X86_64_4LVL;
+        } else if (strcasecmp(user_max_paging_mode_s, "5level") == 0) {
+            user_max_paging_mode = PAGING_MODE_X86_64_5LVL;
+        }
+#elif defined (__aarch64__)
+        if (strcasecmp(user_max_paging_mode_s, "4level") == 0) {
+            user_max_paging_mode = PAGING_MODE_AARCH64_4LVL;
+        } else if (strcasecmp(user_max_paging_mode_s, "5level") == 0) {
+            user_max_paging_mode = PAGING_MODE_AARCH64_5LVL;
+        }
+#elif defined (__riscv64)
+        if (strcasecmp(user_max_paging_mode_s, "sv39") == 0) {
+            user_max_paging_mode = PAGING_MODE_RISCV_SV39;
+        } else if (strcasecmp(user_max_paging_mode_s, "sv48") == 0) {
+            user_max_paging_mode = PAGING_MODE_RISCV_SV48;
+        } else if (strcasecmp(user_max_paging_mode_s, "sv57") == 0) {
+            user_max_paging_mode = PAGING_MODE_RISCV_SV57;
+        }
+#endif
+        else {
+            panic(true, "limine: Invalid MAX_PAGING_MODE: `%s`", user_max_paging_mode_s);
+        }
+    }
+
+    if (user_max_paging_mode < max_supported_paging_mode) {
+        max_supported_paging_mode = user_max_paging_mode;
+    }
+
+#if defined (__x86_64__) || defined (__i386__)
+    paging_mode = PAGING_MODE_X86_64_4LVL;
+#elif defined (__riscv64)
+    paging_mode = max_supported_paging_mode >= PAGING_MODE_RISCV_SV48 ? PAGING_MODE_RISCV_SV48 : PAGING_MODE_RISCV_SV39;
+#else
+    paging_mode = max_supported_paging_mode;
+#endif
+
 #if defined (__riscv64)
 #define paging_mode_limine_to_vmm(x) (PAGING_MODE_RISCV_SV39 + (x))
 #define paging_mode_vmm_to_limine(x) ((x) - PAGING_MODE_RISCV_SV39)
@@ -489,42 +528,9 @@ FEAT_START
     if (pm_request == NULL)
         break;
 
-    uint64_t paging_mode_max = LIMINE_PAGING_MODE_MAX;
-
-    char *max_paging_mode_s = config_get_value(config, 0, "MAX_PAGING_MODE");
-    if (max_paging_mode_s != NULL) {
-#if defined (__x86_64__) || defined (__i386__)
-        if (strcasecmp(max_paging_mode_s, "4level") == 0) {
-            paging_mode_max = LIMINE_PAGING_MODE_X86_64_4LVL;
-        } else if (strcasecmp(max_paging_mode_s, "5level") == 0) {
-            paging_mode_max = LIMINE_PAGING_MODE_X86_64_5LVL;
-        }
-#elif defined (__aarch64__)
-        if (strcasecmp(max_paging_mode_s, "4level") == 0) {
-            paging_mode_max = LIMINE_PAGING_MODE_AARCH64_4LVL;
-        } else if (strcasecmp(max_paging_mode_s, "5level") == 0) {
-            paging_mode_max = LIMINE_PAGING_MODE_AARCH64_5LVL;
-        }
-#elif defined (__riscv64)
-        if (strcasecmp(max_paging_mode_s, "sv39") == 0) {
-            paging_mode_max = LIMINE_PAGING_MODE_RISCV_SV39;
-        } else if (strcasecmp(max_paging_mode_s, "sv48") == 0) {
-            paging_mode_max = LIMINE_PAGING_MODE_RISCV_SV48;
-        } else if (strcasecmp(max_paging_mode_s, "sv57") == 0) {
-            paging_mode_max = LIMINE_PAGING_MODE_RISCV_SV57;
-        }
-#endif
-        else {
-            panic(true, "limine: Invalid MAX_PAGING_MODE: `%s`", max_paging_mode_s);
-        }
-    }
-
     uint64_t target_mode = pm_request->mode;
-    if (pm_request->mode > paging_mode_max) {
-        target_mode = paging_mode_max;
-    }
-
     paging_mode = paging_mode_limine_to_vmm(target_mode);
+
     if (paging_mode > max_supported_paging_mode) {
         paging_mode = max_supported_paging_mode;
     }
@@ -537,7 +543,6 @@ FEAT_START
 
     pm_response->mode = paging_mode_vmm_to_limine(paging_mode);
     pm_request->response = reported_addr(pm_response);
-
 FEAT_END
 
     if (!paging_mode_set) {
tab: 248 wrap: offon