:: commit 15f111f5c32746279233e775ac5d11b50c82fadd

mintsuki <mintsuki@protonmail.com> — 2022-03-31 11:33

parents: 6caaada636

limine: Make WP flag enabled as per spec

diff --git a/PROTOCOL.md b/PROTOCOL.md
index 96d41cec..16a65e54 100644
--- a/PROTOCOL.md
+++ b/PROTOCOL.md
@@ -137,10 +137,9 @@ 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`),
-LME is enabled (`EFER`).
+WP is enabled (`cr0`), LME is enabled (`EFER`), NX is enabled (`EFER`).
 If 5-level paging is requested and available, then 5-level paging is enabled
 (LA57 bit in `cr4`).
-The NX bit will be enabled (NX bit in `EFER`).
 
 The A20 gate is opened.
 
diff --git a/common/protos/limine.c b/common/protos/limine.c
index 514a53b8..d17160a0 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -699,7 +699,7 @@ FEAT_START
                         &cpu_count, &bsp_lapic_id,
                         true, want_5lv,
                         pagemap, smp_request->flags & LIMINE_SMP_X2APIC, true,
-                        direct_map_offset);
+                        direct_map_offset, true);
 
     if (smp_info == NULL) {
         break;
@@ -800,7 +800,7 @@ FEAT_END
     term_runtime = true;
 
     stivale_spinup(64, want_5lv, &pagemap, entry_point, 0,
-                   reported_addr(stack), true, (uintptr_t)local_gdt);
+                   reported_addr(stack), true, true, (uintptr_t)local_gdt);
 
     __builtin_unreachable();
 }
diff --git a/common/protos/stivale.32.c b/common/protos/stivale.32.c
index ed06a5f2..63fc4072 100644
--- a/common/protos/stivale.32.c
+++ b/common/protos/stivale.32.c
@@ -5,7 +5,7 @@
 #include <mm/vmm.h>
 
 noreturn void stivale_spinup_32(
-                 int bits, bool level5pg, bool enable_nx, uint32_t pagemap_top_lv,
+                 int bits, bool level5pg, bool enable_nx, bool wp, uint32_t pagemap_top_lv,
                  uint32_t entry_point_lo, uint32_t entry_point_hi,
                  uint32_t stivale_struct_lo, uint32_t stivale_struct_hi,
                  uint32_t stack_lo, uint32_t stack_hi,
@@ -38,6 +38,15 @@ noreturn void stivale_spinup_32(
             );
         }
 
+        if (wp) {
+            asm volatile (
+                "movl %%cr0, %%eax\n\t"
+                "btsl $16, %%eax\n\t"
+                "movl %%eax, %%cr0\n\t"
+                ::: "eax", "memory"
+            );
+        }
+
         asm volatile (
             "cld\n\t"
             "movl %%eax, %%cr3\n\t"
diff --git a/common/protos/stivale.c b/common/protos/stivale.c
index a8cae28d..5ffdfa52 100644
--- a/common/protos/stivale.c
+++ b/common/protos/stivale.c
@@ -368,7 +368,7 @@ bool stivale_load(char *config, char *cmdline) {
 
     stivale_spinup(bits, want_5lv, &pagemap,
                    entry_point, REPORTED_ADDR((uint64_t)(uintptr_t)stivale_struct),
-                   stivale_hdr.stack, false, (uintptr_t)local_gdt);
+                   stivale_hdr.stack, false, false, (uintptr_t)local_gdt);
 
     __builtin_unreachable();
 
@@ -487,7 +487,7 @@ noreturn void stivale_spinup_32(
 noreturn void stivale_spinup(
                  int bits, bool level5pg, pagemap_t *pagemap,
                  uint64_t entry_point, uint64_t _stivale_struct, uint64_t stack,
-                 bool enable_nx, uint32_t local_gdt) {
+                 bool enable_nx, bool wp, uint32_t local_gdt) {
 #if bios == 1
     if (bits == 64) {
         // If we're going 64, we might as well call this BIOS interrupt
@@ -509,8 +509,8 @@ noreturn void stivale_spinup(
 
     irq_flush_type = IRQ_PIC_APIC_FLUSH;
 
-    common_spinup(stivale_spinup_32, 11,
-        bits, level5pg, enable_nx, (uint32_t)(uintptr_t)pagemap->top_level,
+    common_spinup(stivale_spinup_32, 12,
+        bits, level5pg, enable_nx, wp, (uint32_t)(uintptr_t)pagemap->top_level,
         (uint32_t)entry_point, (uint32_t)(entry_point >> 32),
         (uint32_t)_stivale_struct, (uint32_t)(_stivale_struct >> 32),
         (uint32_t)stack, (uint32_t)(stack >> 32), local_gdt);
diff --git a/common/protos/stivale.h b/common/protos/stivale.h
index 9b7e8e67..83c99d53 100644
--- a/common/protos/stivale.h
+++ b/common/protos/stivale.h
@@ -17,6 +17,6 @@ pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null, struct elf_range
 noreturn void stivale_spinup(
                  int bits, bool level5pg, pagemap_t *pagemap,
                  uint64_t entry_point, uint64_t stivale_struct, uint64_t stack,
-                 bool enable_nx, uint32_t local_gdt);
+                 bool enable_nx, bool wp, uint32_t local_gdt);
 
 #endif
diff --git a/common/protos/stivale2.c b/common/protos/stivale2.c
index 87be3cd1..bc002f09 100644
--- a/common/protos/stivale2.c
+++ b/common/protos/stivale2.c
@@ -765,7 +765,8 @@ have_tm_tag:;
                             &cpu_count, &bsp_lapic_id,
                             bits == 64, want_5lv,
                             pagemap, smp_hdr_tag->flags & 1, want_pmrs,
-                            stivale2_hdr.flags & (1 << 1) ? direct_map_offset : 0);
+                            stivale2_hdr.flags & (1 << 1) ? direct_map_offset : 0,
+                            want_pmrs);
 
         if (smp_info != NULL) {
             tag->tag.identifier = STIVALE2_STRUCT_TAG_SMP_ID;
@@ -833,7 +834,7 @@ have_tm_tag:;
 
     stivale_spinup(bits, want_5lv, &pagemap, entry_point,
                    REPORTED_ADDR((uint64_t)(uintptr_t)stivale2_struct),
-                   stivale2_hdr.stack, want_pmrs, (uintptr_t)local_gdt);
+                   stivale2_hdr.stack, want_pmrs, want_pmrs, (uintptr_t)local_gdt);
 
     __builtin_unreachable();
 
diff --git a/common/sys/smp.c b/common/sys/smp.c
index 3c60518c..2c29b353 100644
--- a/common/sys/smp.c
+++ b/common/sys/smp.c
@@ -54,7 +54,7 @@ struct trampoline_passed_info {
 static bool smp_start_ap(uint32_t lapic_id, struct gdtr *gdtr,
                          struct smp_information *info_struct,
                          bool longmode, bool lv5, uint32_t pagemap,
-                         bool x2apic, bool nx, uint64_t hhdm) {
+                         bool x2apic, bool nx, uint64_t hhdm, bool wp) {
     size_t trampoline_size = (size_t)_binary_smp_trampoline_bin_end
                            - (size_t)_binary_smp_trampoline_bin_start;
 
@@ -78,6 +78,7 @@ static bool smp_start_ap(uint32_t lapic_id, struct gdtr *gdtr,
     passed_info->smp_tpl_target_mode = ((uint32_t)x2apic << 2)
                         | ((uint32_t)lv5 << 1)
                         | ((uint32_t)nx << 3)
+                        | ((uint32_t)wp << 4)
                         | (uint32_t)longmode;
     passed_info->smp_tpl_gdt         = *gdtr;
     passed_info->smp_tpl_booted_flag = 0;
@@ -122,7 +123,8 @@ struct smp_information *init_smp(size_t    header_hack_size,
                                  pagemap_t pagemap,
                                  bool      x2apic,
                                  bool      nx,
-                                 uint64_t  hhdm) {
+                                 uint64_t  hhdm,
+                                 bool      wp) {
     if (!lapic_check())
         return NULL;
 
@@ -227,7 +229,7 @@ struct smp_information *init_smp(size_t    header_hack_size,
                 // Try to start the AP
                 if (!smp_start_ap(lapic->lapic_id, &gdtr, info_struct,
                                   longmode, lv5, (uintptr_t)pagemap.top_level,
-                                  x2apic, nx, hhdm)) {
+                                  x2apic, nx, hhdm, wp)) {
                     print("smp: FAILED to bring-up AP\n");
                     continue;
                 }
@@ -264,7 +266,7 @@ struct smp_information *init_smp(size_t    header_hack_size,
                 // Try to start the AP
                 if (!smp_start_ap(x2lapic->x2apic_id, &gdtr, info_struct,
                                   longmode, lv5, (uintptr_t)pagemap.top_level,
-                                  true, nx, hhdm)) {
+                                  true, nx, hhdm, wp)) {
                     print("smp: FAILED to bring-up AP\n");
                     continue;
                 }
diff --git a/common/sys/smp.h b/common/sys/smp.h
index df272871..6ac759e0 100644
--- a/common/sys/smp.h
+++ b/common/sys/smp.h
@@ -23,6 +23,7 @@ struct smp_information *init_smp(size_t    header_hack_size,
                                  pagemap_t pagemap,
                                  bool      x2apic,
                                  bool      nx,
-                                 uint64_t  hhdm);
+                                 uint64_t  hhdm,
+                                 bool      wp);
 
 #endif
diff --git a/common/sys/smp_trampoline.real b/common/sys/smp_trampoline.real
index 0bf44d0d..56b94e08 100644
--- a/common/sys/smp_trampoline.real
+++ b/common/sys/smp_trampoline.real
@@ -101,6 +101,14 @@ smp_trampoline:
     wrmsr
 
   .nonx:
+    test dword [rbx + passed_info.target_mode], (1 << 4)
+    jz .nowp
+
+    mov rax, cr0
+    bts rax, 16
+    mov cr0, rax
+
+  .nowp:
     mov rax, qword [rbx + passed_info.hhdm]
     add qword [rbx + passed_info.gdtr + 2], rax
     lgdt [rbx + passed_info.gdtr]
tab: 248 wrap: offon