stivale2: Implement slide HHDM header tag

This commit is contained in:
mintsuki 2021-11-24 15:44:17 +01:00
parent 6bcbfe9b48
commit 01255704bd
4 changed files with 61 additions and 13 deletions

View File

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

View File

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

View File

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

View File

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