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) {
