stivale2: Implement PMRs
This commit is contained in:
parent
79b8c38c8c
commit
de3c7eed67
@ -8,7 +8,7 @@
|
||||
#include <mm/pmm.h>
|
||||
#include <fs/file.h>
|
||||
|
||||
#define KASLR_SLIDE_BITMASK ((uintptr_t)0x3ffff000)
|
||||
#define KASLR_SLIDE_BITMASK ((uintptr_t)0x8ffff000)
|
||||
|
||||
#define PT_LOAD 0x00000001
|
||||
#define PT_INTERP 0x00000003
|
||||
@ -420,7 +420,7 @@ int elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *top, uint64_t *_sl
|
||||
|
||||
again:
|
||||
if (kaslr)
|
||||
slide = rand64() & KASLR_SLIDE_BITMASK;
|
||||
slide = (rand64() & KASLR_SLIDE_BITMASK) & (min_align - 1);
|
||||
|
||||
final:
|
||||
if (top)
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <mm/vmm.h>
|
||||
|
||||
__attribute__((noreturn)) void stivale_spinup_32(
|
||||
int bits, bool level5pg, uint32_t pagemap_top_lv,
|
||||
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) {
|
||||
@ -15,6 +15,16 @@ __attribute__((noreturn)) void stivale_spinup_32(
|
||||
};
|
||||
|
||||
if (bits == 64) {
|
||||
if (enable_nx) {
|
||||
asm volatile (
|
||||
"movl $0xc0000080, %%ecx\n\t"
|
||||
"rdmsr\n\t"
|
||||
"btsl $11, %%eax\n\t"
|
||||
"wrmsr\n\t"
|
||||
::: "eax", "ecx", "edx", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
if (level5pg) {
|
||||
// Enable CR4.LA57
|
||||
asm volatile (
|
||||
|
@ -295,7 +295,7 @@ void 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);
|
||||
stivale_hdr.stack, false);
|
||||
}
|
||||
|
||||
pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null, struct elf_range *ranges, size_t ranges_count) {
|
||||
@ -307,20 +307,16 @@ pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null, struct elf_range
|
||||
for (uint64_t i = 0; i < 0x80000000; i += 0x200000) {
|
||||
map_page(pagemap, 0xffffffff80000000 + i, i, 0x03, true);
|
||||
}
|
||||
|
||||
// Sub 2MiB mappings
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < ranges_count; i++) {
|
||||
uint64_t virt = ranges[i].base;
|
||||
uint64_t phys = virt;
|
||||
|
||||
if (phys & ((uint64_t)1 << 63))
|
||||
if (phys & ((uint64_t)1 << 63)) {
|
||||
phys -= FIXED_HIGHER_HALF_OFFSET_64;
|
||||
} else {
|
||||
panic("stivale2: Protected memory ranges are only supported for higher half kernels");
|
||||
}
|
||||
|
||||
uint64_t pf = VMM_FLAG_PRESENT |
|
||||
(ranges[i].permissions & ELF_PF_X ? 0 : VMM_FLAG_NOEXEC) |
|
||||
@ -332,6 +328,13 @@ pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null, struct elf_range
|
||||
}
|
||||
}
|
||||
|
||||
// Sub 2MiB mappings
|
||||
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 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);
|
||||
@ -382,7 +385,8 @@ __attribute__((noreturn)) void stivale_spinup_32(
|
||||
|
||||
__attribute__((noreturn)) void stivale_spinup(
|
||||
int bits, bool level5pg, pagemap_t *pagemap,
|
||||
uint64_t entry_point, uint64_t _stivale_struct, uint64_t stack) {
|
||||
uint64_t entry_point, uint64_t _stivale_struct, uint64_t stack,
|
||||
bool enable_nx) {
|
||||
#if bios == 1
|
||||
if (bits == 64) {
|
||||
// If we're going 64, we might as well call this BIOS interrupt
|
||||
@ -395,11 +399,15 @@ __attribute__((noreturn)) void stivale_spinup(
|
||||
}
|
||||
#endif
|
||||
|
||||
if (enable_nx) {
|
||||
vmm_assert_nx();
|
||||
}
|
||||
|
||||
pic_mask_all();
|
||||
pic_flush();
|
||||
|
||||
common_spinup(stivale_spinup_32, 9,
|
||||
bits, level5pg, (uint32_t)(uintptr_t)pagemap->top_level,
|
||||
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));
|
||||
|
@ -13,6 +13,7 @@ bool stivale_load_by_anchor(void **_anchor, const char *magic,
|
||||
pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null, struct elf_range *ranges, size_t ranges_count);
|
||||
__attribute__((noreturn)) void stivale_spinup(
|
||||
int bits, bool level5pg, pagemap_t *pagemap,
|
||||
uint64_t entry_point, uint64_t stivale_struct, uint64_t stack);
|
||||
uint64_t entry_point, uint64_t stivale_struct, uint64_t stack,
|
||||
bool enable_nx);
|
||||
|
||||
#endif
|
||||
|
@ -81,6 +81,9 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table
|
||||
uint64_t slide = 0;
|
||||
uint64_t entry_point = 0;
|
||||
|
||||
struct elf_range *ranges;
|
||||
uint64_t ranges_count;
|
||||
|
||||
uint8_t *kernel = freadall(kernel_file, STIVALE2_MMAP_BOOTLOADER_RECLAIMABLE);
|
||||
int bits = elf_bits(kernel);
|
||||
bool loaded_by_anchor = false;
|
||||
@ -99,6 +102,8 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table
|
||||
loaded_by_anchor = true;
|
||||
}
|
||||
|
||||
bool want_pmrs = false;
|
||||
|
||||
int ret = 0;
|
||||
switch (bits) {
|
||||
case 64: {
|
||||
@ -114,9 +119,25 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table
|
||||
}
|
||||
|
||||
if (!loaded_by_anchor) {
|
||||
ret = elf64_load_section(kernel, &stivale2_hdr, ".stivale2hdr",
|
||||
sizeof(struct stivale2_header), 0);
|
||||
if (ret) {
|
||||
goto failed_to_load_header_section;
|
||||
}
|
||||
|
||||
if ((stivale2_hdr.flags & (1 << 2))) {
|
||||
if (bits == 32) {
|
||||
panic("stivale2: PMRs are not supported for 32-bit kernels");
|
||||
} else if (loaded_by_anchor) {
|
||||
panic("stivale2: PMRs are not supported for anchored kernels");
|
||||
}
|
||||
want_pmrs = true;
|
||||
}
|
||||
|
||||
if (elf64_load(kernel, &entry_point, NULL, &slide,
|
||||
STIVALE2_MMAP_KERNEL_AND_MODULES, kaslr, false,
|
||||
NULL, NULL))
|
||||
want_pmrs ? &ranges : NULL,
|
||||
want_pmrs ? &ranges_count : NULL))
|
||||
panic("stivale2: ELF64 load failure");
|
||||
|
||||
ret = elf64_load_section(kernel, &stivale2_hdr, ".stivale2hdr",
|
||||
@ -142,6 +163,7 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table
|
||||
|
||||
printv("stivale2: %u-bit kernel detected\n", bits);
|
||||
|
||||
failed_to_load_header_section:
|
||||
switch (ret) {
|
||||
case 1:
|
||||
panic("stivale2: File is not a valid ELF.");
|
||||
@ -462,6 +484,25 @@ skip_modeset:;
|
||||
(void)pxe;
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// Create PMRs struct tag
|
||||
//////////////////////////////////////////////
|
||||
{
|
||||
if (want_pmrs) {
|
||||
struct stivale2_struct_tag_pmrs *tag =
|
||||
ext_mem_alloc(sizeof(struct stivale2_struct_tag_pmrs)
|
||||
+ ranges_count * sizeof(struct stivale2_pmr));
|
||||
|
||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_PMRS_ID;
|
||||
|
||||
tag->entries = ranges_count;
|
||||
|
||||
memcpy(tag->pmrs, ranges, ranges_count * sizeof(struct stivale2_pmr));
|
||||
|
||||
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// Create EFI system table struct tag
|
||||
//////////////////////////////////////////////
|
||||
@ -480,7 +521,9 @@ skip_modeset:;
|
||||
|
||||
pagemap_t pagemap = {0};
|
||||
if (bits == 64)
|
||||
pagemap = stivale_build_pagemap(want_5lv, unmap_null, NULL, 0);
|
||||
pagemap = stivale_build_pagemap(want_5lv, unmap_null,
|
||||
want_pmrs ? ranges : NULL,
|
||||
want_pmrs ? ranges_count : 0);
|
||||
|
||||
#if uefi == 1
|
||||
efi_exit_boot_services();
|
||||
@ -499,7 +542,7 @@ skip_modeset:;
|
||||
smp_info = init_smp(sizeof(struct stivale2_struct_tag_smp), (void **)&tag,
|
||||
&cpu_count, &bsp_lapic_id,
|
||||
bits == 64, want_5lv,
|
||||
pagemap, smp_hdr_tag->flags & 1);
|
||||
pagemap, smp_hdr_tag->flags & 1, want_pmrs);
|
||||
|
||||
if (smp_info != NULL) {
|
||||
tag->tag.identifier = STIVALE2_STRUCT_TAG_SMP_ID;
|
||||
@ -557,5 +600,5 @@ skip_modeset:;
|
||||
|
||||
stivale_spinup(bits, want_5lv, &pagemap, entry_point,
|
||||
REPORTED_ADDR((uint64_t)(uintptr_t)&stivale2_struct),
|
||||
stivale2_hdr.stack);
|
||||
stivale2_hdr.stack, want_pmrs);
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ struct trampoline_passed_info {
|
||||
static bool smp_start_ap(uint32_t lapic_id, struct gdtr *gdtr,
|
||||
struct smp_information *info_struct,
|
||||
bool longmode, bool lv5, uint32_t pagemap,
|
||||
bool x2apic) {
|
||||
bool x2apic, bool nx) {
|
||||
size_t trampoline_size = (size_t)_binary_smp_trampoline_bin_end
|
||||
- (size_t)_binary_smp_trampoline_bin_start;
|
||||
|
||||
@ -81,6 +81,7 @@ static bool smp_start_ap(uint32_t lapic_id, struct gdtr *gdtr,
|
||||
passed_info->smp_tpl_pagemap = pagemap;
|
||||
passed_info->smp_tpl_target_mode = ((uint32_t)x2apic << 2)
|
||||
| ((uint32_t)lv5 << 1)
|
||||
| ((uint32_t)nx << 3)
|
||||
| (uint32_t)longmode;
|
||||
passed_info->smp_tpl_gdt = *gdtr;
|
||||
passed_info->smp_tpl_booted_flag = 0;
|
||||
@ -122,7 +123,8 @@ struct smp_information *init_smp(size_t header_hack_size,
|
||||
bool longmode,
|
||||
bool lv5,
|
||||
pagemap_t pagemap,
|
||||
bool x2apic) {
|
||||
bool x2apic,
|
||||
bool nx) {
|
||||
if (!lapic_check())
|
||||
return NULL;
|
||||
|
||||
@ -227,7 +229,7 @@ struct smp_information *init_smp(size_t header_hack_size,
|
||||
// Try to start the AP
|
||||
if (!smp_start_ap(lapic->lapic_id, &gdtr, info_struct,
|
||||
longmode, lv5, (uintptr_t)pagemap.top_level,
|
||||
x2apic)) {
|
||||
x2apic, nx)) {
|
||||
print("smp: FAILED to bring-up AP\n");
|
||||
continue;
|
||||
}
|
||||
@ -264,7 +266,7 @@ struct smp_information *init_smp(size_t header_hack_size,
|
||||
// Try to start the AP
|
||||
if (!smp_start_ap(x2lapic->x2apic_id, &gdtr, info_struct,
|
||||
longmode, lv5, (uintptr_t)pagemap.top_level,
|
||||
true)) {
|
||||
true, nx)) {
|
||||
print("smp: FAILED to bring-up AP\n");
|
||||
continue;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ struct smp_information *init_smp(size_t header_hack_size,
|
||||
bool longmode,
|
||||
bool lv5,
|
||||
pagemap_t pagemap,
|
||||
bool x2apic);
|
||||
bool x2apic,
|
||||
bool nx);
|
||||
|
||||
#endif
|
||||
|
@ -56,6 +56,11 @@ smp_trampoline:
|
||||
bts eax, 5
|
||||
mov cr4, eax
|
||||
|
||||
mov ecx, 0xc0000080
|
||||
mov eax, 0x100
|
||||
xor edx, edx
|
||||
wrmsr
|
||||
|
||||
test dword [ebx + passed_info.target_mode], (1 << 1)
|
||||
jz .no5lv
|
||||
|
||||
@ -67,11 +72,6 @@ smp_trampoline:
|
||||
mov eax, dword [ebx + passed_info.pagemap]
|
||||
mov cr3, eax
|
||||
|
||||
mov ecx, 0xc0000080
|
||||
mov eax, 0x100
|
||||
xor edx, edx
|
||||
wrmsr
|
||||
|
||||
mov eax, cr0
|
||||
bts eax, 31
|
||||
mov cr0, eax
|
||||
@ -91,6 +91,16 @@ smp_trampoline:
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
|
||||
mov ebx, ebx
|
||||
test dword [rbx + passed_info.target_mode], (1 << 3)
|
||||
jz .nonx
|
||||
|
||||
mov ecx, 0xc0000080
|
||||
rdmsr
|
||||
bts eax, 11
|
||||
wrmsr
|
||||
|
||||
.nonx:
|
||||
jmp parking64
|
||||
|
||||
bits 32
|
||||
|
@ -42,7 +42,7 @@ __attribute__((section(".stivale2hdr"), used))
|
||||
struct stivale2_header header2 = {
|
||||
.entry_point = (uint64_t)stivale2_main,
|
||||
.stack = (uintptr_t)stacks[0] + sizeof(stack),
|
||||
.flags = 1 << 1,
|
||||
.flags = (1 << 1) | (1 << 2),
|
||||
.tags = (uint64_t)&framebuffer_request
|
||||
};
|
||||
|
||||
@ -184,6 +184,15 @@ void stivale2_main(struct stivale2_struct *info) {
|
||||
e9_printf("Kernel slide: %x", t->kernel_slide);
|
||||
break;
|
||||
}
|
||||
case STIVALE2_STRUCT_TAG_PMRS_ID: {
|
||||
struct stivale2_struct_tag_pmrs *t = (struct stivale2_struct_tag_pmrs *)tag;
|
||||
e9_puts("PMRs tag:");
|
||||
e9_printf("\t%d ranges:", t->entries);
|
||||
for (size_t i = 0; i < t->entries; i++) {
|
||||
e9_printf("\t\tBase: %x Length: %x Perms: %x",
|
||||
t->pmrs[i].base, t->pmrs[i].length, t->pmrs[i].permissions);
|
||||
}
|
||||
}
|
||||
case STIVALE2_STRUCT_TAG_SMP_ID: {
|
||||
struct stivale2_struct_tag_smp *s = (struct stivale2_struct_tag_smp *)tag;
|
||||
e9_puts("SMP tag:");
|
||||
|
Loading…
Reference in New Issue
Block a user