mirror of
https://github.com/limine-bootloader/limine
synced 2024-11-24 17:39:40 +03:00
protos/limine: Change minimum supported paging mode depending on HHDM span, fail if span too large
This commit is contained in:
parent
64385a9d86
commit
f6c8097c78
@ -34,6 +34,37 @@
|
||||
|
||||
#define MAX_REQUESTS 128
|
||||
|
||||
static uint64_t get_hhdm_span_top(int base_revision) {
|
||||
uint64_t ret = 0x100000000;
|
||||
for (size_t i = 0; i < memmap_entries; i++) {
|
||||
if (base_revision >= 1 && (
|
||||
memmap[i].type == MEMMAP_RESERVED
|
||||
|| memmap[i].type == MEMMAP_BAD_MEMORY)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint64_t base = memmap[i].base;
|
||||
uint64_t length = memmap[i].length;
|
||||
uint64_t top = base + length;
|
||||
|
||||
if (base < 0x100000000) {
|
||||
base = 0x100000000;
|
||||
}
|
||||
|
||||
if (base >= top) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint64_t aligned_top = ALIGN_UP(top, 0x40000000);
|
||||
|
||||
if (aligned_top > ret) {
|
||||
ret = aligned_top;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static pagemap_t build_pagemap(int base_revision,
|
||||
int paging_mode, bool nx, struct elf_range *ranges, size_t ranges_count,
|
||||
uint64_t physical_base, uint64_t virtual_base,
|
||||
@ -204,7 +235,8 @@ static void **requests;
|
||||
static void set_paging_mode(int paging_mode, bool kaslr) {
|
||||
direct_map_offset = paging_mode_higher_half(paging_mode);
|
||||
if (kaslr) {
|
||||
uint64_t mask = ((uint64_t)1 << (paging_mode_va_bits(paging_mode) - 4)) - 1;
|
||||
// Half of the higher half of wiggle room for KASLR, align to 1GiB steps.
|
||||
uint64_t mask = ((uint64_t)1 << (paging_mode_va_bits(paging_mode) - 2)) - 1;
|
||||
direct_map_offset += (rand64() & ~((uint64_t)0x40000000 - 1)) & mask;
|
||||
}
|
||||
}
|
||||
@ -446,12 +478,15 @@ noreturn void limine_load(char *config, char *cmdline) {
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64_t hhdm_span_top = get_hhdm_span_top(base_revision);
|
||||
|
||||
printv("limine: Physical base: %X\n", physical_base);
|
||||
printv("limine: Virtual base: %X\n", virtual_base);
|
||||
printv("limine: Slide: %X\n", slide);
|
||||
printv("limine: ELF entry point: %X\n", entry_point);
|
||||
printv("limine: Base revision: %u\n", base_revision);
|
||||
printv("limine: Requests count: %u\n", requests_count);
|
||||
printv("limine: Top of HHDM: %X\n", hhdm_span_top);
|
||||
|
||||
// Paging Mode
|
||||
int paging_mode, max_supported_paging_mode, min_supported_paging_mode;
|
||||
@ -463,17 +498,49 @@ noreturn void limine_load(char *config, char *cmdline) {
|
||||
max_supported_paging_mode = PAGING_MODE_X86_64_5LVL;
|
||||
}
|
||||
min_supported_paging_mode = PAGING_MODE_X86_64_4LVL;
|
||||
if (hhdm_span_top >= ((uint64_t)1 << paging_mode_va_bits(min_supported_paging_mode)) - (kaslr ? 2 : 1)) {
|
||||
min_supported_paging_mode = PAGING_MODE_X86_64_5LVL;
|
||||
if (min_supported_paging_mode > max_supported_paging_mode) {
|
||||
goto hhdm_fail;
|
||||
}
|
||||
}
|
||||
if (hhdm_span_top >= ((uint64_t)1 << paging_mode_va_bits(min_supported_paging_mode)) - (kaslr ? 2 : 1)) {
|
||||
goto hhdm_fail;
|
||||
}
|
||||
#elif defined (__aarch64__)
|
||||
max_supported_paging_mode = PAGING_MODE_AARCH64_4LVL;
|
||||
min_supported_paging_mode = PAGING_MODE_AARCH64_4LVL;
|
||||
if (hhdm_span_top >= ((uint64_t)1 << paging_mode_va_bits(min_supported_paging_mode)) - (kaslr ? 2 : 1)) {
|
||||
goto hhdm_fail;
|
||||
}
|
||||
// TODO(qookie): aarch64 also has optional 5 level paging when using 4K pages
|
||||
#elif defined (__riscv64)
|
||||
max_supported_paging_mode = vmm_max_paging_mode();
|
||||
min_supported_paging_mode = PAGING_MODE_RISCV_SV39;
|
||||
if (hhdm_span_top >= ((uint64_t)1 << paging_mode_va_bits(min_supported_paging_mode)) - (kaslr ? 2 : 1)) {
|
||||
min_supported_paging_mode = PAGING_MODE_RISCV_SV48;
|
||||
if (min_supported_paging_mode > max_supported_paging_mode) {
|
||||
goto hhdm_fail;
|
||||
}
|
||||
}
|
||||
if (hhdm_span_top >= ((uint64_t)1 << paging_mode_va_bits(min_supported_paging_mode)) - (kaslr ? 2 : 1)) {
|
||||
min_supported_paging_mode = PAGING_MODE_RISCV_SV57;
|
||||
if (min_supported_paging_mode > max_supported_paging_mode) {
|
||||
goto hhdm_fail;
|
||||
}
|
||||
}
|
||||
if (hhdm_span_top >= ((uint64_t)1 << paging_mode_va_bits(min_supported_paging_mode)) - (kaslr ? 2 : 1)) {
|
||||
goto hhdm_fail;
|
||||
}
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
||||
if (0) {
|
||||
hhdm_fail:
|
||||
panic(true, "limine: Unable to allocate higher half direct map (too much memory?)");
|
||||
}
|
||||
|
||||
char *user_paging_mode_s = config_get_value(config, 0, "PAGING_MODE");
|
||||
|
||||
int user_max_paging_mode = PAGING_MODE_MAX;
|
||||
|
Loading…
Reference in New Issue
Block a user