:: commit 4bd3a540a8a2727e36c4d9b55e602c6299d90d8a

mintsuki <mintsuki@protonmail.com> — 2021-05-04 13:17

parents: 07d9f7d7ee

stivale: Implement higher half returned addresses flag

diff --git a/stage23/protos/stivale.32.c b/stage23/protos/stivale.32.c
index 2f24f19b..346cad0d 100644
--- a/stage23/protos/stivale.32.c
+++ b/stage23/protos/stivale.32.c
@@ -6,11 +6,13 @@
 __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,
-                 void *stivale_struct, uint32_t stack_lo, uint32_t stack_hi) {
-    uint64_t entry_point =
-        (uint64_t)entry_point_lo | ((uint64_t)entry_point_hi << 32);
-    uint64_t stack =
-        (uint64_t)stack_lo | ((uint64_t)stack_hi << 32);
+                 uint32_t stivale_struct_lo, uint32_t stivale_struct_hi,
+                 uint32_t stack_lo, uint32_t stack_hi) {
+    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)
+    };
 
     if (bits == 64) {
         if (level5pg) {
@@ -52,14 +54,15 @@ __attribute__((noreturn)) void stivale_spinup_32(
 
             // Since we don't really know what is now present in the upper
             // 32 bits of the 64 bit registers, clear up the upper bits
-            // of the registers we use to store stack pointer and instruction
-            // pointer
+            // of the register that points to the 64-bit casted value array.
             "mov esi, esi\n\t"
-            "mov ebx, ebx\n\t"
-            "mov edi, edi\n\t"
+
+            // Move in 64-bit values
+            "mov rdi, qword ptr [rsi + 0]\n\t"
+            "mov rbx, qword ptr [rsi + 8]\n\t"
+            "mov rsi, qword ptr [rsi + 16]\n\t"
 
             // Let's pretend we push a return address
-            "mov rsi, qword ptr [rsi]\n\t"
             "test rsi, rsi\n\t"
             "jz 1f\n\t"
 
@@ -71,7 +74,7 @@ __attribute__((noreturn)) void stivale_spinup_32(
             "push rsi\n\t"
             "pushfq\n\t"
             "push 0x28\n\t"
-            "push [rbx]\n\t"
+            "push rbx\n\t"
 
             "xor rax, rax\n\t"
             "xor rbx, rbx\n\t"
@@ -91,8 +94,7 @@ __attribute__((noreturn)) void stivale_spinup_32(
             "iretq\n\t"
             ".code32\n\t"
             :
-            : "a" (pagemap_top_lv), "b" (&entry_point),
-              "D" (stivale_struct), "S" (&stack)
+            : "a" (pagemap_top_lv), "S" (casted_to_64)
             : "memory"
         );
     } else if (bits == 32) {
@@ -100,13 +102,13 @@ __attribute__((noreturn)) void stivale_spinup_32(
             "cli\n\t"
             "cld\n\t"
 
-            "mov esp, dword ptr [esi]\n\t"
+            "mov esp, esi\n\t"
             "push edi\n\t"
             "push 0\n\t"
 
             "pushfd\n\t"
             "push 0x18\n\t"
-            "push [ebx]\n\t"
+            "push ebx\n\t"
 
             "xor eax, eax\n\t"
             "xor ebx, ebx\n\t"
@@ -118,7 +120,9 @@ __attribute__((noreturn)) void stivale_spinup_32(
 
             "iret\n\t"
             :
-            : "b"(&entry_point), "D"(stivale_struct), "S"(&stack)
+            : "D" ((uint32_t)casted_to_64[0]),
+              "b" ((uint32_t)casted_to_64[1]),
+              "S" ((uint32_t)casted_to_64[2])
             : "memory"
         );
     }
diff --git a/stage23/protos/stivale.c b/stage23/protos/stivale.c
index 64eb2d0d..0e606c2c 100644
--- a/stage23/protos/stivale.c
+++ b/stage23/protos/stivale.c
@@ -22,6 +22,10 @@
 #include <stivale/stivale.h>
 #include <drivers/vga_textmode.h>
 
+#define REPORTED_ADDR(PTR) \
+    ((PTR) + ((stivale_hdr.flags & (1 << 3)) ? \
+    (want_5lv ? 0xff00000000000000 : 0xffff800000000000) : 0))
+
 struct stivale_struct stivale_struct = {0};
 
 void stivale_load(char *config, char *cmdline) {
@@ -105,6 +109,9 @@ void stivale_load(char *config, char *cmdline) {
             panic("stivale: Section .stivalehdr is smaller than size of the struct.");
     }
 
+    bool want_5lv = level5pg && (stivale_hdr.flags & (1 << 1));
+    pagemap_t pagemap = stivale_build_pagemap(want_5lv, false);
+
     if (stivale_hdr.entry_point != 0)
         entry_point = stivale_hdr.entry_point;
 
@@ -141,11 +148,11 @@ void stivale_load(char *config, char *cmdline) {
         if (!uri_open(&f, module_path))
             panic("Requested module with path \"%s\" not found!", module_path);
 
-        m->begin = (uint64_t)(size_t)freadall(&f, STIVALE_MMAP_KERNEL_AND_MODULES);
+        m->begin = REPORTED_ADDR((uint64_t)(size_t)freadall(&f, STIVALE_MMAP_KERNEL_AND_MODULES));
         m->end   = m->begin + f.size;
         m->next  = 0;
 
-        *prev_mod_ptr = (uint64_t)(size_t)m;
+        *prev_mod_ptr = REPORTED_ADDR((uint64_t)(size_t)m);
         prev_mod_ptr  = &m->next;
 
         print("stivale: Requested module %u:\n", i);
@@ -155,12 +162,20 @@ void stivale_load(char *config, char *cmdline) {
         print("         End:    %X\n", m->end);
     }
 
-    stivale_struct.rsdp = (uint64_t)(size_t)acpi_get_rsdp();
+    uint64_t rsdp = (uint64_t)(size_t)acpi_get_rsdp();
+
+    if (rsdp)
+        stivale_struct.rsdp = REPORTED_ADDR(rsdp);
 
-    acpi_get_smbios((void **)&stivale_struct.smbios_entry_32,
-                    (void **)&stivale_struct.smbios_entry_64);
+    uint64_t smbios_entry_32 = 0, smbios_entry_64 = 0;
+    acpi_get_smbios((void **)&smbios_entry_32, (void **)&smbios_entry_64);
 
-    stivale_struct.cmdline = (uint64_t)(size_t)cmdline;
+    if (smbios_entry_32)
+        stivale_struct.smbios_entry_32 = REPORTED_ADDR(smbios_entry_32);
+    if (smbios_entry_64)
+        stivale_struct.smbios_entry_64 = REPORTED_ADDR(smbios_entry_64);
+
+    stivale_struct.cmdline = REPORTED_ADDR((uint64_t)(size_t)cmdline);
 
     stivale_struct.epoch = time();
     print("stivale: Current epoch: %U\n", stivale_struct.epoch);
@@ -184,7 +199,7 @@ void stivale_load(char *config, char *cmdline) {
                            (uint64_t)fbinfo.framebuffer_pitch * fbinfo.framebuffer_height,
                            MEMMAP_FRAMEBUFFER, false, false, false, true);
 
-        stivale_struct.framebuffer_addr    = (uint64_t)fbinfo.framebuffer_addr;
+        stivale_struct.framebuffer_addr    = REPORTED_ADDR((uint64_t)fbinfo.framebuffer_addr);
         stivale_struct.framebuffer_width   = fbinfo.framebuffer_width;
         stivale_struct.framebuffer_height  = fbinfo.framebuffer_height;
         stivale_struct.framebuffer_bpp     = fbinfo.framebuffer_bpp;
@@ -209,9 +224,6 @@ void stivale_load(char *config, char *cmdline) {
     efi_exit_boot_services();
 #endif
 
-    bool want_5lv = level5pg && (stivale_hdr.flags & (1 << 1));
-    pagemap_t pagemap = stivale_build_pagemap(want_5lv, false);
-
     // Reserve 32K at 0x70000
     memmap_alloc_range(0x70000, 0x8000, MEMMAP_USABLE, true, true, false, false);
 
@@ -219,10 +231,11 @@ void stivale_load(char *config, char *cmdline) {
     struct e820_entry_t *memmap = get_memmap(&memmap_entries);
 
     stivale_struct.memory_map_entries = (uint64_t)memmap_entries;
-    stivale_struct.memory_map_addr    = (uint64_t)(size_t)memmap;
+    stivale_struct.memory_map_addr    = REPORTED_ADDR((uint64_t)(size_t)memmap);
 
     stivale_spinup(bits, want_5lv, &pagemap,
-                   entry_point, &stivale_struct, stivale_hdr.stack);
+                   entry_point, REPORTED_ADDR((uint64_t)(uintptr_t)&stivale_struct),
+                   stivale_hdr.stack);
 }
 
 pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null) {
@@ -286,11 +299,12 @@ extern symbol ImageBase;
 __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,
-                 void *stivale_struct, uint32_t stack_lo, uint32_t stack_hi);
+                 uint32_t stivale_struct_lo, uint32_t stivale_struct_hi,
+                 uint32_t stack_lo, uint32_t stack_hi);
 
 __attribute__((noreturn)) void stivale_spinup(
                  int bits, bool level5pg, pagemap_t *pagemap,
-                 uint64_t entry_point, void *stivale_struct, uint64_t stack) {
+                 uint64_t entry_point, uint64_t stivale_struct, uint64_t stack) {
 #if defined (bios)
     if (bits == 64) {
         // If we're going 64, we might as well call this BIOS interrupt
@@ -307,17 +321,17 @@ __attribute__((noreturn)) void stivale_spinup(
     pic_flush();
 
 #if defined (uefi)
-    do_32(stivale_spinup_32, 8,
+    do_32(stivale_spinup_32, 9,
         bits, level5pg, (uint32_t)(uintptr_t)pagemap->top_level,
         (uint32_t)entry_point, (uint32_t)(entry_point >> 32),
-        stivale_struct,
+        (uint32_t)stivale_struct, (uint32_t)(stivale_struct >> 32),
         (uint32_t)stack, (uint32_t)(stack >> 32));
 #endif
 
 #if defined (bios)
     stivale_spinup_32(bits, level5pg, (uint32_t)(uintptr_t)pagemap->top_level,
         (uint32_t)entry_point, (uint32_t)(entry_point >> 32),
-        stivale_struct,
+        (uint32_t)stivale_struct, (uint32_t)(stivale_struct >> 32),
         (uint32_t)stack, (uint32_t)(stack >> 32));
 #endif
 
diff --git a/stage23/protos/stivale.h b/stage23/protos/stivale.h
index 45cd8fef..b1983b61 100644
--- a/stage23/protos/stivale.h
+++ b/stage23/protos/stivale.h
@@ -11,6 +11,6 @@ void stivale_load(char *config, char *cmdline);
 pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null);
 __attribute__((noreturn)) void stivale_spinup(
                  int bits, bool level5pg, pagemap_t *pagemap,
-                 uint64_t entry_point, void *stivale_struct, uint64_t stack);
+                 uint64_t entry_point, uint64_t stivale_struct, uint64_t stack);
 
 #endif
diff --git a/stage23/protos/stivale2.c b/stage23/protos/stivale2.c
index abf4a908..c859fe9d 100644
--- a/stage23/protos/stivale2.c
+++ b/stage23/protos/stivale2.c
@@ -494,5 +494,5 @@ skip_modeset:;
     term_write("\e[2J\e[H", 7);
 
     stivale_spinup(bits, level5pg && level5pg_requested, &pagemap,
-                   entry_point, &stivale2_struct, stivale2_hdr.stack);
+                   entry_point, (uint64_t)(uintptr_t)&stivale2_struct, stivale2_hdr.stack);
 }
diff --git a/test/stivale.c b/test/stivale.c
index d3b80a63..89133092 100644
--- a/test/stivale.c
+++ b/test/stivale.c
@@ -12,12 +12,13 @@ struct stivale_header header = {
     .framebuffer_bpp    = 0,
     .framebuffer_width  = 0,
     .framebuffer_height = 0,
-    .flags              = 1,
+    .flags              = 1 | (1 << 3),
     .entry_point        = (uint64_t)(uintptr_t)stivale_main
 };
 
 void stivale_main(struct stivale_struct *info) {
-    // Print some info.
+    e9_printf("Stivale struct at %x", info);
+
     e9_puts("Stivale information passed to the kernel:");
     e9_printf("Cmdline: %s", (char*)info->cmdline);
     e9_printf("Memory map at %x with contents:", info->memory_map_addr);
@@ -55,7 +56,7 @@ void stivale_main(struct stivale_struct *info) {
     struct stivale_module *modules = ((struct stivale_module *)(info->modules));
     for (size_t i = 0; i < info->module_count; i++) {
         struct stivale_module e = *modules;
-        e9_printf("\tModule %d: [%x+%x] %s", i, e.begin, e.end, e.string);
+        e9_printf("\tModule %d: [%x->%x] %s", i, e.begin, e.end, e.string);
         modules = (struct stivale_module *)e.next;
     }
 
tab: 248 wrap: offon