:: commit d3385da3e339b8796e8ba558cdadee877fe18123

mintsuki <mintsuki@protonmail.com> — 2022-09-02 01:31

parents: c44f514738

limine: Make NX feature not mandatory

diff --git a/PROTOCOL.md b/PROTOCOL.md
index 5ace4d65..616789c0 100644
--- a/PROTOCOL.md
+++ b/PROTOCOL.md
@@ -139,7 +139,7 @@ IF flag, VM flag, and direction flag are cleared on entry. Other flags
 undefined.
 
 PG is enabled (`cr0`), PE is enabled (`cr0`), PAE is enabled (`cr4`),
-WP is enabled (`cr0`), LME is enabled (`EFER`), NX is enabled (`EFER`).
+WP is enabled (`cr0`), LME is enabled (`EFER`), NX is enabled (`EFER`) if available.
 If 5-level paging is requested and available, then 5-level paging is enabled
 (LA57 bit in `cr4`).
 
diff --git a/common/mm/vmm.c b/common/mm/vmm.c
index a1103572..e2bdd7da 100644
--- a/common/mm/vmm.c
+++ b/common/mm/vmm.c
@@ -28,13 +28,6 @@ static pt_entry_t *get_next_level(pagemap_t pagemap, pt_entry_t *current_level,
 #define PT_IS_LARGE(x) (((x) & (PT_FLAG_VALID | PT_FLAG_LARGE)) == (PT_FLAG_VALID | PT_FLAG_LARGE))
 #define PT_TO_VMM_FLAGS(x) ((x) & (PT_FLAG_WRITE | PT_FLAG_NX))
 
-void vmm_assert_nx(void) {
-    uint32_t a, b, c, d;
-    if (!cpuid(0x80000001, 0, &a, &b, &c, &d) || !(d & (1 << 20))) {
-        panic(false, "vmm: NX functionality not available on this CPU.");
-    }
-}
-
 pagemap_t new_pagemap(int lv) {
     pagemap_t pagemap;
     pagemap.levels    = lv;
diff --git a/common/mm/vmm.h b/common/mm/vmm.h
index 3031da3b..3927c9bc 100644
--- a/common/mm/vmm.h
+++ b/common/mm/vmm.h
@@ -21,7 +21,6 @@ enum page_size {
     Size1GiB
 };
 
-void vmm_assert_nx(void);
 pagemap_t new_pagemap(int lv);
 void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags, enum page_size page_size);
 
diff --git a/common/protos/limine.c b/common/protos/limine.c
index f565743a..4b2735da 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -862,6 +862,14 @@ FEAT_END
     efi_exit_boot_services();
 #endif
 
+#if defined (__x86_64__) || defined (__i386__)
+    // Check if we have NX
+    bool nx_available = false;
+    if (cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx) && (edx & (1 << 20))) {
+        nx_available = true;
+    }
+#endif
+
     // SMP
 FEAT_START
     struct limine_smp_request *smp_request = get_request(LIMINE_SMP_REQUEST);
@@ -877,7 +885,7 @@ FEAT_START
     smp_info = init_smp(0, (void **)&smp_array,
                         &cpu_count, &bsp_lapic_id,
                         true, want_5lv,
-                        pagemap, smp_request->flags & LIMINE_SMP_X2APIC, true,
+                        pagemap, smp_request->flags & LIMINE_SMP_X2APIC, nx_available,
                         direct_map_offset, true);
 #elif defined (__aarch64__)
     uint64_t bsp_mpidr;
@@ -1004,8 +1012,6 @@ FEAT_END
     rm_int(0x15, &r, &r);
 #endif
 
-    vmm_assert_nx();
-
     pic_mask_all();
     io_apic_mask_all();
 
@@ -1013,11 +1019,11 @@ FEAT_END
 
     uint64_t reported_stack = reported_addr(stack);
 
-    common_spinup(limine_spinup_32, 7,
+    common_spinup(limine_spinup_32, 8,
         want_5lv, (uint32_t)(uintptr_t)pagemap.top_level,
         (uint32_t)entry_point, (uint32_t)(entry_point >> 32),
         (uint32_t)reported_stack, (uint32_t)(reported_stack >> 32),
-        (uint32_t)(uintptr_t)local_gdt);
+        (uint32_t)(uintptr_t)local_gdt, nx_available);
 #elif defined (__aarch64__)
     vmm_assert_4k_pages();
 
diff --git a/common/protos/limine_32.asm_x86 b/common/protos/limine_32.asm_x86
index 94ac426f..60a7e0a1 100644
--- a/common/protos/limine_32.asm_x86
+++ b/common/protos/limine_32.asm_x86
@@ -5,10 +5,13 @@ section .text
 global limine_spinup_32
 limine_spinup_32:
     ; Enable EFER.NXE
+    cmp dword [esp+32], 0 ; nx_available
+    je .no_nx
     mov ecx, 0xc0000080
     rdmsr
     bts eax, 11
     wrmsr
+  .no_nx:
 
     ; Enable CR4.LA57
     cmp dword [esp+4], 0 ; level5pg
tab: 248 wrap: offon