stivale: Initial infrastructure to support ELF permissions

This commit is contained in:
mintsuki 2021-07-15 14:09:12 +02:00
parent 178f3cea0e
commit 79b8c38c8c
5 changed files with 45 additions and 13 deletions

View File

@ -3,11 +3,19 @@
#include <mm/vmm.h>
#include <mm/pmm.h>
#include <lib/blib.h>
#include <sys/cpu.h>
#define PT_SIZE ((uint64_t)0x1000)
typedef uint64_t pt_entry_t;
void vmm_assert_nx(void) {
uint32_t a, b, c, d;
if (!cpuid(0x80000001, 0, &a, &b, &c, &d) || !(d & (1 << 20))) {
panic("vmm: NX functionality not available on this CPU.");
}
}
static pt_entry_t *get_next_level(pt_entry_t *current_level, size_t entry) {
pt_entry_t *ret;

View File

@ -4,11 +4,16 @@
#include <stdint.h>
#include <stdbool.h>
#define VMM_FLAG_PRESENT ((uint64_t)1 << 0)
#define VMM_FLAG_WRITE ((uint64_t)1 << 1)
#define VMM_FLAG_NOEXEC ((uint64_t)1 << 63)
typedef struct {
int levels;
void *top_level;
} pagemap_t;
void vmm_assert_nx(void);
pagemap_t new_pagemap(int lv);
void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags, bool hugepages);

View File

@ -282,7 +282,7 @@ void stivale_load(char *config, char *cmdline) {
pagemap_t pagemap = {0};
if (bits == 64)
pagemap = stivale_build_pagemap(want_5lv, false);
pagemap = stivale_build_pagemap(want_5lv, false, NULL, 0);
// Reserve 32K at 0x70000
memmap_alloc_range(0x70000, 0x8000, MEMMAP_USABLE, true, true, false, false);
@ -298,20 +298,38 @@ void stivale_load(char *config, char *cmdline) {
stivale_hdr.stack);
}
pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null) {
pagemap_t stivale_build_pagemap(bool level5pg, bool unmap_null, struct elf_range *ranges, size_t ranges_count) {
pagemap_t pagemap = new_pagemap(level5pg ? 5 : 4);
uint64_t higher_half_base = level5pg ? 0xff00000000000000 : 0xffff800000000000;
// Map 0 to 2GiB at 0xffffffff80000000
for (uint64_t i = 0; i < 0x80000000; i += 0x200000) {
map_page(pagemap, 0xffffffff80000000 + i, i, 0x03, true);
}
if (ranges_count == 0) {
// Map 0 to 2GiB at 0xffffffff80000000
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);
// 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))
phys -= FIXED_HIGHER_HALF_OFFSET_64;
uint64_t pf = VMM_FLAG_PRESENT |
(ranges[i].permissions & ELF_PF_X ? 0 : VMM_FLAG_NOEXEC) |
(ranges[i].permissions & ELF_PF_W ? VMM_FLAG_WRITE : 0);
for (uint64_t j = 0; j < ranges[i].length; j += 0x1000) {
map_page(pagemap, virt + j, phys + j, pf, false);
}
}
}
// Map 2MiB to 4GiB at higher half base and 0

View File

@ -4,12 +4,13 @@
#include <stdbool.h>
#include <stdint.h>
#include <mm/vmm.h>
#include <lib/elf.h>
void 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);
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);

View File

@ -480,7 +480,7 @@ skip_modeset:;
pagemap_t pagemap = {0};
if (bits == 64)
pagemap = stivale_build_pagemap(want_5lv, unmap_null);
pagemap = stivale_build_pagemap(want_5lv, unmap_null, NULL, 0);
#if uefi == 1
efi_exit_boot_services();