stivale: Implement higher half returned addresses flag

This commit is contained in:
mintsuki 2021-05-04 15:17:36 +02:00
parent 07d9f7d7ee
commit 4bd3a540a8
5 changed files with 57 additions and 38 deletions

View File

@ -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"
);
}

View File

@ -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();
acpi_get_smbios((void **)&stivale_struct.smbios_entry_32,
(void **)&stivale_struct.smbios_entry_64);
if (rsdp)
stivale_struct.rsdp = REPORTED_ADDR(rsdp);
stivale_struct.cmdline = (uint64_t)(size_t)cmdline;
uint64_t smbios_entry_32 = 0, smbios_entry_64 = 0;
acpi_get_smbios((void **)&smbios_entry_32, (void **)&smbios_entry_64);
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

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}