From 2f844f3f48ba8463f81fcd868d1538d1c307464d Mon Sep 17 00:00:00 2001 From: mintsuki Date: Thu, 25 Nov 2021 22:46:16 +0100 Subject: [PATCH] stivale1&2: Pass higher half GDTR.base when returning higher half pointers --- stage23/protos/stivale.32.c | 10 ++++++++-- stage23/protos/stivale.c | 21 ++++++++++++++++----- stage23/protos/stivale.h | 2 +- stage23/protos/stivale2.c | 14 +++++++++++++- stage23/sys/gdt.h | 2 +- 5 files changed, 39 insertions(+), 10 deletions(-) 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 #include #include +#include #include #include #include @@ -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));