:: commit 62b042a2fe37295d9204b38ff6c4c24317b76593

mintsuki <mintsuki@protonmail.com> — 2021-03-07 05:50

parents: 058da70164

Get SMP to work on UEFI

diff --git a/stage23/mm/mtrr.32.c b/stage23/mm/mtrr.32.c
new file mode 100644
index 00000000..8ea988cd
--- /dev/null
+++ b/stage23/mm/mtrr.32.c
@@ -0,0 +1,28 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <mm/mtrr.h>
+#include <sys/cpu.h>
+#include <lib/blib.h>
+
+static bool mtrr_supported(void) {
+    uint32_t eax, ebx, ecx, edx;
+
+    if (!cpuid(1, 0, &eax, &ebx, &ecx, &edx))
+        return false;
+
+    return !!(edx & (1 << 12));
+}
+
+void mtrr_restore_32(struct mtrr *saved_mtrr) {
+    if (!mtrr_supported())
+        return;
+
+    uint64_t ia32_mtrrcap = rdmsr(0xfe);
+
+    uint8_t var_reg_count = ia32_mtrrcap & 0xff;
+
+    for (uint8_t i = 0; i < var_reg_count; i++) {
+        wrmsr(0x200 + i * 2,     saved_mtrr[i].base);
+        wrmsr(0x200 + i * 2 + 1, saved_mtrr[i].mask);
+    }
+}
diff --git a/stage23/mm/mtrr.c b/stage23/mm/mtrr.c
index 4c900f20..bcd24346 100644
--- a/stage23/mm/mtrr.c
+++ b/stage23/mm/mtrr.c
@@ -6,11 +6,6 @@
 #include <lib/print.h>
 #include <lib/blib.h>
 
-struct mtrr {
-    uint64_t base;
-    uint64_t mask;
-};
-
 static bool mtrr_supported(void) {
     uint32_t eax, ebx, ecx, edx;
 
@@ -107,7 +102,7 @@ bool mtrr_set_range(uint64_t base, uint64_t size, uint8_t memory_type) {
     return false;
 }
 
-static struct mtrr *saved_mtrr = NULL;
+struct mtrr *saved_mtrr = NULL;
 
 void mtrr_save(void) {
     if (!mtrr_supported())
diff --git a/stage23/mm/mtrr.h b/stage23/mm/mtrr.h
index 9f76136d..7fae542f 100644
--- a/stage23/mm/mtrr.h
+++ b/stage23/mm/mtrr.h
@@ -10,8 +10,16 @@
 #define MTRR_MEMORY_TYPE_WP 0x05
 #define MTRR_MEMORY_TYPE_WB 0x06
 
+struct mtrr {
+    uint64_t base;
+    uint64_t mask;
+};
+
+extern struct mtrr *saved_mtrr;
+
 void mtrr_save(void);
 void mtrr_restore(void);
+void mtrr_restore_32(struct mtrr *saved_mtrr);
 bool mtrr_set_range(uint64_t base, uint64_t size, uint8_t caching_type);
 
 #endif
diff --git a/stage23/protos/stivale.c b/stage23/protos/stivale.c
index 4b2a66d4..4386235a 100644
--- a/stage23/protos/stivale.c
+++ b/stage23/protos/stivale.c
@@ -200,6 +200,10 @@ void stivale_load(char *config, char *cmdline) {
     stivale_struct.memory_map_entries = (uint64_t)memmap_entries;
     stivale_struct.memory_map_addr    = (uint64_t)(size_t)memmap;
 
+#if defined (uefi)
+    efi_exit_boot_services();
+#endif
+
     stivale_spinup(bits, want_5lv, &pagemap,
                    entry_point, &stivale_struct, stivale_hdr.stack);
 }
@@ -271,10 +275,6 @@ __attribute__((noreturn)) void stivale_spinup(
     }
 #endif
 
-#if defined (uefi)
-    efi_exit_boot_services();
-#endif
-
     pic_mask_all();
     pic_flush();
 
diff --git a/stage23/protos/stivale2.c b/stage23/protos/stivale2.c
index bcfc0570..7b5044e1 100644
--- a/stage23/protos/stivale2.c
+++ b/stage23/protos/stivale2.c
@@ -299,6 +299,10 @@ void stivale2_load(char *config, char *cmdline, bool pxe) {
     if (bits == 64)
         pagemap = stivale_build_pagemap(level5pg && level5pg_requested);
 
+#if defined (uefi)
+    efi_exit_boot_services();
+#endif
+
     //////////////////////////////////////////////
     // Create SMP struct tag
     //////////////////////////////////////////////
diff --git a/stage23/sys/gdt.h b/stage23/sys/gdt.h
index e8eaf4a2..35f36a04 100644
--- a/stage23/sys/gdt.h
+++ b/stage23/sys/gdt.h
@@ -4,8 +4,8 @@
 #include <stdint.h>
 
 struct gdtr {
-    uint16_t  limit;
-    uintptr_t ptr;
+    uint16_t limit;
+    uint64_t ptr;
 } __attribute__((packed));
 
 struct gdt_desc {
diff --git a/stage23/sys/smp.c b/stage23/sys/smp.c
index 138d602c..da56568d 100644
--- a/stage23/sys/smp.c
+++ b/stage23/sys/smp.c
@@ -52,8 +52,9 @@ struct trampoline_passed_info {
     uint8_t  smp_tpl_booted_flag;
     uint8_t  smp_tpl_target_mode;
     uint32_t smp_tpl_pagemap;
-    void *mtrr_restore_vector;
-    struct smp_information *smp_tpl_info_struct;
+    uint32_t mtrr_restore_vector;
+    uint32_t saved_mtrr_ptr;
+    uint32_t smp_tpl_info_struct;
     struct gdtr smp_tpl_gdt;
 } __attribute__((packed));
 
@@ -78,14 +79,19 @@ static bool smp_start_ap(uint32_t lapic_id, struct gdtr *gdtr,
                                - sizeof(struct trampoline_passed_info));
     }
 
-    passed_info->smp_tpl_info_struct = info_struct;
+    passed_info->smp_tpl_info_struct = (uint32_t)(uintptr_t)info_struct;
     passed_info->smp_tpl_booted_flag = 0;
     passed_info->smp_tpl_pagemap     = pagemap;
     passed_info->smp_tpl_target_mode = ((uint32_t)x2apic << 2)
                         | ((uint32_t)lv5 << 1)
                         | (uint32_t)longmode;
     passed_info->smp_tpl_gdt         = *gdtr;
-    passed_info->mtrr_restore_vector = mtrr_restore;
+#if defined (bios)
+    passed_info->mtrr_restore_vector = (uint32_t)(uintptr_t)mtrr_restore;
+#elif defined (uefi)
+    passed_info->mtrr_restore_vector = (uint32_t)(uintptr_t)mtrr_restore_32;
+#endif
+    passed_info->saved_mtrr_ptr      = (uint32_t)(uintptr_t)saved_mtrr;
     passed_info->smp_tpl_booted_flag = 0;
 
     asm volatile ("" ::: "memory");
@@ -135,8 +141,7 @@ struct smp_information *init_smp(size_t    header_hack_size,
     if (madt == NULL)
         return NULL;
 
-    struct gdtr gdtr;
-    asm volatile ("sgdt %0" :: "m"(gdtr) : "memory");
+    struct gdtr gdtr = gdt;
 
     uint32_t eax, ebx, ecx, edx;
 
diff --git a/stage23/sys/smp_trampoline.real b/stage23/sys/smp_trampoline.real
index fcc24dc9..c7c42ca9 100644
--- a/stage23/sys/smp_trampoline.real
+++ b/stage23/sys/smp_trampoline.real
@@ -5,11 +5,10 @@ smp_trampoline:
     cli
     cld
 
-jmp $
     mov ebx, cs
     shl ebx, 4
 
-    lgdt [cs:passed_info.gdtr]
+    o32 lgdt [cs:passed_info.gdtr]
 
     lea eax, [ebx + .mode32]
     mov [cs:.farjmp_off], eax
@@ -49,7 +48,9 @@ jmp $
   .nox2apic:
     lea esp, [ebx + temp_stack.top]
 
+    push dword [ebx + passed_info.saved_mtrr_ptr]
     call [ebx + passed_info.mtrr_restore_vector]
+    add esp, 4
 
     test dword [ebx + passed_info.target_mode], (1 << 0)
     jz parking32
@@ -169,7 +170,8 @@ passed_info:
     .target_mode db 0
     .pagemap dd 0
     .mtrr_restore_vector dd 0
+    .saved_mtrr_ptr dd 0
     .smp_info_struct dd 0
     .gdtr:
         dw 0
-        dd 0
+        dq 0
tab: 248 wrap: offon