From 01255704bd1853ae9924b4708f1ec0bd103a1109 Mon Sep 17 00:00:00 2001 From: mintsuki Date: Wed, 24 Nov 2021 15:44:17 +0100 Subject: [PATCH] stivale2: Implement slide HHDM header tag --- stage23/protos/stivale.c | 18 +++++++++++------- stage23/protos/stivale.h | 3 ++- stage23/protos/stivale2.c | 37 +++++++++++++++++++++++++++++++++---- test/stivale2.c | 16 +++++++++++++++- 4 files changed, 61 insertions(+), 13 deletions(-) diff --git a/stage23/protos/stivale.c b/stage23/protos/stivale.c index f11935bc..2b0359ab 100644 --- a/stage23/protos/stivale.c +++ b/stage23/protos/stivale.c @@ -26,7 +26,7 @@ #define REPORTED_ADDR(PTR) \ ((PTR) + ((stivale_hdr.flags & (1 << 3)) ? \ - (want_5lv ? 0xff00000000000000 : 0xffff800000000000) : 0)) + direct_map_offset : 0)) bool stivale_load_by_anchor(void **_anchor, const char *magic, uint8_t *file, uint64_t filesize) { @@ -185,6 +185,8 @@ bool stivale_load(char *config, char *cmdline) { bool want_5lv = level5pg && (stivale_hdr.flags & (1 << 1)); + uint64_t direct_map_offset = want_5lv ? 0xff00000000000000 : 0xffff800000000000; + if (stivale_hdr.entry_point != 0) entry_point = stivale_hdr.entry_point; @@ -329,7 +331,7 @@ bool stivale_load(char *config, char *cmdline) { pagemap_t pagemap = {0}; if (bits == 64) - pagemap = stivale_build_pagemap(want_5lv, false, NULL, 0, false, 0, 0); + pagemap = stivale_build_pagemap(want_5lv, false, NULL, 0, false, 0, 0, direct_map_offset); // Reserve 32K at 0x70000 if possible if (!memmap_alloc_range(0x70000, 0x8000, MEMMAP_USABLE, true, false, false, false)) { @@ -356,15 +358,17 @@ bool stivale_load(char *config, char *cmdline) { entry_point, REPORTED_ADDR((uint64_t)(uintptr_t)&stivale_struct), stivale_hdr.stack, false); + __builtin_unreachable(); + fail: pmm_free(kernel, kernel_file_size); return false; } pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null, struct elf_range *ranges, size_t ranges_count, - bool want_fully_virtual, uint64_t physical_base, uint64_t virtual_base) { + bool want_fully_virtual, uint64_t physical_base, uint64_t virtual_base, + uint64_t direct_map_offset) { pagemap_t pagemap = new_pagemap(level5pg ? 5 : 4); - uint64_t higher_half_base = level5pg ? 0xff00000000000000 : 0xffff800000000000; if (ranges_count == 0) { // Map 0 to 2GiB at 0xffffffff80000000 @@ -400,13 +404,13 @@ pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null, struct elf_range for (uint64_t i = 0; i < 0x200000; i += 0x1000) { if (!(i == 0 && unmap_null)) map_page(pagemap, i, i, 0x03, false); - map_page(pagemap, higher_half_base + i, i, 0x03, false); + map_page(pagemap, direct_map_offset + i, i, 0x03, false); } // Map 2MiB to 4GiB at higher half base and 0 for (uint64_t i = 0x200000; i < 0x100000000; i += 0x200000) { map_page(pagemap, i, i, 0x03, true); - map_page(pagemap, higher_half_base + i, i, 0x03, true); + map_page(pagemap, direct_map_offset + i, i, 0x03, true); } size_t _memmap_entries = memmap_entries; @@ -434,7 +438,7 @@ pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null, struct elf_range for (uint64_t j = 0; j < aligned_length; j += 0x200000) { uint64_t page = aligned_base + j; map_page(pagemap, page, page, 0x03, true); - map_page(pagemap, higher_half_base + page, page, 0x03, true); + map_page(pagemap, direct_map_offset + page, page, 0x03, true); } } diff --git a/stage23/protos/stivale.h b/stage23/protos/stivale.h index a52b75b3..c5f43ac6 100644 --- a/stage23/protos/stivale.h +++ b/stage23/protos/stivale.h @@ -11,7 +11,8 @@ bool stivale_load(char *config, char *cmdline); bool stivale_load_by_anchor(void **_anchor, const char *magic, uint8_t *file, uint64_t filesize); pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null, struct elf_range *ranges, size_t ranges_count, - bool want_fully_virtual, uint64_t physical_base, uint64_t virtual_base); + bool want_fully_virtual, uint64_t physical_base, uint64_t virtual_base, + uint64_t direct_map_offset); __attribute__((noreturn)) void stivale_spinup( int bits, bool level5pg, pagemap_t *pagemap, uint64_t entry_point, uint64_t stivale_struct, uint64_t stack, diff --git a/stage23/protos/stivale2.c b/stage23/protos/stivale2.c index 3c79f4fc..ac32d6a1 100644 --- a/stage23/protos/stivale2.c +++ b/stage23/protos/stivale2.c @@ -25,10 +25,11 @@ #include #include #include +#include #define REPORTED_ADDR(PTR) \ ((PTR) + ((stivale2_hdr.flags & (1 << 1)) ? \ - (want_5lv ? 0xff00000000000000 : 0xffff800000000000) : 0)) + direct_map_offset : 0)) struct stivale2_struct stivale2_struct = {0}; @@ -232,6 +233,19 @@ failed_to_load_header_section: bool want_5lv = (get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_5LV_PAGING_ID) ? true : false) && level5pg; + uint64_t direct_map_offset = want_5lv ? 0xff00000000000000 : 0xffff800000000000; + + { + struct stivale2_header_tag_slide_hhdm *slt = get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_SLIDE_HHDM_ID); + if (slt != NULL) { + if (slt->alignment % 0x200000 != 0 || slt->alignment == 0) { + panic("stivale2: Requested HHDM slide alignment is not a multiple of 2MiB"); + } + + direct_map_offset += (rand64() & ~(slt->alignment - 1)) & 0xffffffffff; + } + } + if (stivale2_hdr.entry_point != 0) entry_point = stivale2_hdr.entry_point; @@ -624,6 +638,18 @@ have_tm_tag:; } } + ////////////////////////////////////////////// + // Create HHDM struct tag + ////////////////////////////////////////////// + { + struct stivale2_struct_tag_hhdm *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_hhdm)); + tag->tag.identifier = STIVALE2_STRUCT_TAG_HHDM_ID; + + tag->addr = direct_map_offset; + + append_tag(&stivale2_struct, (struct stivale2_tag *)tag); + } + #if bios == 1 ////////////////////////////////////////////// // Create PXE struct tag @@ -693,7 +719,8 @@ have_tm_tag:; pagemap = stivale_build_pagemap(want_5lv, unmap_null, want_pmrs ? ranges : NULL, want_pmrs ? ranges_count : 0, - want_fully_virtual, physical_base, virtual_base); + want_fully_virtual, physical_base, virtual_base, + direct_map_offset); #if uefi == 1 efi_exit_boot_services(); @@ -762,11 +789,11 @@ have_tm_tag:; if (verbose) { print("stivale2: Generated tags:\n"); struct stivale2_tag *taglist = - (void*)(uintptr_t)(stivale2_struct.tags & (uint64_t)0xffffffff); + (void*)(uintptr_t)(stivale2_struct.tags - ((stivale2_hdr.flags & (1 << 1)) ? direct_map_offset : 0)); for (size_t i = 0; ; i++) { print(" Tag #%u ID: %X\n", i, taglist->identifier); if (taglist->next) { - taglist = (void*)(uintptr_t)(taglist->next & (uint64_t)0xffffffff); + taglist = (void*)(uintptr_t)(taglist->next - ((stivale2_hdr.flags & (1 << 1)) ? direct_map_offset : 0)); } else { break; } @@ -782,6 +809,8 @@ have_tm_tag:; REPORTED_ADDR((uint64_t)(uintptr_t)&stivale2_struct), stivale2_hdr.stack, want_pmrs); + __builtin_unreachable(); + fail: pmm_free(kernel, kernel_file_size); return false; diff --git a/test/stivale2.c b/test/stivale2.c index 2f58d529..5f107a63 100644 --- a/test/stivale2.c +++ b/test/stivale2.c @@ -7,10 +7,19 @@ typedef uint8_t stack[4096]; static stack stacks[64] = {0}; void stivale2_main(struct stivale2_struct *info); +struct stivale2_header_tag_slide_hhdm slide_hhdm = { + .tag = { + .identifier = STIVALE2_HEADER_TAG_SLIDE_HHDM_ID, + .next = 0 + }, + .flags = 0, + .alignment = 0x10000000 +}; + struct stivale2_header_tag_terminal terminal_request = { .tag = { .identifier = STIVALE2_HEADER_TAG_TERMINAL_ID, - .next = 0 + .next = (uint64_t)&slide_hhdm }, .flags = 0 }; @@ -204,6 +213,11 @@ void stivale2_main(struct stivale2_struct *info) { } break; } + case STIVALE2_STRUCT_TAG_HHDM_ID: { + struct stivale2_struct_tag_hhdm *t = (struct stivale2_struct_tag_hhdm *)tag; + e9_printf("Higher half direct map at: %x", t->addr); + break; + } case STIVALE2_STRUCT_TAG_KERNEL_BASE_ADDRESS_ID: { struct stivale2_struct_tag_kernel_base_address *t = (void *)tag; e9_puts("Kernel base address:");