stivale2: Implement slide HHDM header tag
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 <pxe/tftp.h>
#include <drivers/edid.h>
#include <drivers/vga_textmode.h>
+#include <lib/rand.h>
#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:");
