:: commit 2f844f3f48ba8463f81fcd868d1538d1c307464d

mintsuki <mintsuki@protonmail.com> — 2021-11-25 21:46

parents: eea96cda9c

stivale1&2: Pass higher half GDTR.base when returning higher half pointers

diff --git a/stage23/protos/stivale.32.c b/stage23/protos/stivale.32.c
index ad9c1a23..4370f312 100644
--- a/stage23/protos/stivale.32.c
+++ b/stage23/protos/stivale.32.c
@@ -7,11 +7,13 @@ __attribute__((noreturn)) void stivale_spinup_32(
                  int bits, bool level5pg, bool enable_nx, 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) {
+                 uint32_t stack_lo, uint32_t stack_hi,
+                 uint32_t local_gdt) {
     uint64_t casted_to_64[] = {
         (uint64_t)stivale_struct_lo | ((uint64_t)stivale_struct_hi << 32),
         (uint64_t)entry_point_lo | ((uint64_t)entry_point_hi << 32),
-        (uint64_t)stack_lo | ((uint64_t)stack_hi << 32)
+        (uint64_t)stack_lo | ((uint64_t)stack_hi << 32),
+        (uint64_t)local_gdt
     };
 
     if (bits == 64) {
@@ -70,8 +72,12 @@ __attribute__((noreturn)) void stivale_spinup_32(
             // Move in 64-bit values
             "movq 0x00(%%rsi), %%rdi\n\t"
             "movq 0x08(%%rsi), %%rbx\n\t"
+            "movq 0x18(%%rsi), %%rax\n\t"
             "movq 0x10(%%rsi), %%rsi\n\t"
 
+            // Load 64 bit GDT
+            "lgdt (%%rax)\n\t"
+
             // Let's pretend we push a return address
             "testq %%rsi, %%rsi\n\t"
             "jz 1f\n\t"
diff --git a/stage23/protos/stivale.c b/stage23/protos/stivale.c
index f51b238f..a5b995ba 100644
--- a/stage23/protos/stivale.c
+++ b/stage23/protos/stivale.c
@@ -187,6 +187,17 @@ bool stivale_load(char *config, char *cmdline) {
 
     uint64_t direct_map_offset = want_5lv ? 0xff00000000000000 : 0xffff800000000000;
 
+    struct gdtr *local_gdt = ext_mem_alloc(sizeof(struct gdtr));
+    local_gdt->limit = gdt.limit;
+    uint64_t local_gdt_base = (uint64_t)gdt.ptr;
+    if (stivale_hdr.flags & (1 << 3)) {
+        local_gdt_base += direct_map_offset;
+    }
+    local_gdt->ptr = local_gdt_base;
+#if bios == 1
+    local_gdt->ptr_hi = local_gdt_base >> 32;
+#endif
+
     if (stivale_hdr.entry_point != 0)
         entry_point = stivale_hdr.entry_point;
 
@@ -356,7 +367,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);
+                   stivale_hdr.stack, false, (uintptr_t)local_gdt);
 
     __builtin_unreachable();
 
@@ -454,12 +465,12 @@ __attribute__((noreturn)) void stivale_spinup_32(
                  int bits, bool level5pg, 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);
+                 uint32_t stack_lo, uint32_t stack_hi, uint32_t local_gdt);
 
 __attribute__((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) {
+                 bool enable_nx, uint32_t local_gdt) {
 #if bios == 1
     if (bits == 64) {
         // If we're going 64, we might as well call this BIOS interrupt
@@ -481,9 +492,9 @@ __attribute__((noreturn)) void stivale_spinup(
 
     irq_flush_type = IRQ_PIC_APIC_FLUSH;
 
-    common_spinup(stivale_spinup_32, 10,
+    common_spinup(stivale_spinup_32, 11,
         bits, level5pg, enable_nx, (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));
+        (uint32_t)stack, (uint32_t)(stack >> 32), local_gdt);
 }
diff --git a/stage23/protos/stivale.h b/stage23/protos/stivale.h
index c5f43ac6..cb743e7c 100644
--- a/stage23/protos/stivale.h
+++ b/stage23/protos/stivale.h
@@ -16,6 +16,6 @@ pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null, struct elf_range
 __attribute__((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);
+                 bool enable_nx, uint32_t local_gdt);
 
 #endif
diff --git a/stage23/protos/stivale2.c b/stage23/protos/stivale2.c
index 844917c9..038b82d2 100644
--- a/stage23/protos/stivale2.c
+++ b/stage23/protos/stivale2.c
@@ -15,6 +15,7 @@
 #include <lib/uri.h>
 #include <sys/smp.h>
 #include <sys/cpu.h>
+#include <sys/gdt.h>
 #include <lib/fb.h>
 #include <lib/term.h>
 #include <sys/pic.h>
@@ -246,6 +247,17 @@ failed_to_load_header_section:
         }
     }
 
+    struct gdtr *local_gdt = ext_mem_alloc(sizeof(struct gdtr));
+    local_gdt->limit = gdt.limit;
+    uint64_t local_gdt_base = (uint64_t)gdt.ptr;
+    if (stivale2_hdr.flags & (1 << 1)) {
+        local_gdt_base += direct_map_offset;
+    }
+    local_gdt->ptr = local_gdt_base;
+#if bios == 1
+    local_gdt->ptr_hi = local_gdt_base >> 32;
+#endif
+
     if (stivale2_hdr.entry_point != 0)
         entry_point = stivale2_hdr.entry_point;
 
@@ -807,7 +819,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);
+                   stivale2_hdr.stack, want_pmrs, (uintptr_t)local_gdt);
 
     __builtin_unreachable();
 
diff --git a/stage23/sys/gdt.h b/stage23/sys/gdt.h
index 1c93687e..2297c085 100644
--- a/stage23/sys/gdt.h
+++ b/stage23/sys/gdt.h
@@ -9,7 +9,7 @@ struct gdtr {
     uint64_t ptr;
 #elif defined (__i386__)
     uint32_t ptr;
-    uint32_t pad;
+    uint32_t ptr_hi;
 #endif
 } __attribute__((packed));
 
tab: 248 wrap: offon