diff options
| -rw-r--r-- | kc/boot/Makefile | 2 | ||||
| -rw-r--r-- | kc/boot/kc_main.c | 121 | ||||
| -rw-r--r-- | kc/boot/loader_paging.c | 69 | ||||
| -rw-r--r-- | kc/boot/loader_paging.h | 29 |
4 files changed, 122 insertions, 99 deletions
diff --git a/kc/boot/Makefile b/kc/boot/Makefile index 36d069e..159fec1 100644 --- a/kc/boot/Makefile +++ b/kc/boot/Makefile @@ -9,7 +9,7 @@ TARGET := efi.os CPPFLAGS += -I../../api -I ../api OBJS := entry_x86_64.o reloc_x86_64.o kc_main.o elf64.o memcmp.o memcpy.o \ - memmove.o memset.o + memmove.o memset.o loader_paging.o DEPS := $(patsubst %.o,%.d,$(OBJS)) diff --git a/kc/boot/kc_main.c b/kc/boot/kc_main.c index 84609ed..e689535 100644 --- a/kc/boot/kc_main.c +++ b/kc/boot/kc_main.c @@ -1,7 +1,8 @@ +#include "loader_paging.h" + #include <loader/efi/shim.h> #include <kernel/entry.h> #include <kernel/memory/range.h> -#include <kernel/memory/paging.h> #include <stdbool.h> @@ -49,14 +50,6 @@ static struct kc_boot_data *k_boot_data; static void *object_space_base; static size_t object_space_size; -enum page_type -{ - INVALID_PAGE_TYPE = 0x0, - CODE_PAGE_TYPE = PAGE_PR, - RODATA_PAGE_TYPE = PAGE_PR, - DATA_PAGE_TYPE = PAGE_PR|PAGE_WR -}; - static inline void debug() { __asm__ volatile @@ -79,7 +72,7 @@ static inline void plog(CHAR16 *message) if (eto) eto->OutputString(eto, message); } -static uint64_t *new_page_table(void) +uint64_t *new_page_table(void) { EFI_PHYSICAL_ADDRESS table; EFI_STATUS status; @@ -97,64 +90,6 @@ static uint64_t *new_page_table(void) return (uint64_t *)table; } -static uint64_t *get_page_map(void) -{ - uint64_t map; - __asm__("mov %%cr3, %0" : "=r"(map)); - return (uint64_t *)(page_address(map, 1)); -} - -void set_page_map(uint64_t *map) -{ - __asm__ volatile - ( - "pushf\n\t" - "cli\n\t" - "mov %0, %%cr3\n\t" - "popf\n\t" - : - : "r"(map)); -} - -static uint64_t *get_page_table(uint64_t *map, uint64_t virt, int level) -{ - if ((level < 1) || (level > PAGE_MAP_LEVELS)) - { - return NULL; - } - - for (int i = PAGE_MAP_LEVELS; i > level; i--) - { - if (!map[pte_index(virt, i)]) - { - uint64_t *next_map = new_page_table(); - map[pte_index(virt, i)] = (uint64_t)next_map|PAGE_PR|PAGE_WR; - map = next_map; - } - else - { - map = (uint64_t *)page_address(map[pte_index(virt, i)], 1); - } - } - - return map; -} - -static uint64_t *get_page_entry(uint64_t *map, uint64_t virt) -{ - int level = 1; - uint64_t *table = get_page_table(map, virt, level); - return &table[pte_index(virt, level)]; -} - -static void map_page(void *map, - uint64_t virt, - uint64_t phys, - enum page_type type) -{ - *get_page_entry(map, virt) = phys | type; -} - enum page_type get_page_type(Elf64_Phdr *phdr) { switch (phdr->p_flags) @@ -170,20 +105,7 @@ enum page_type get_page_type(Elf64_Phdr *phdr) return INVALID_PAGE_TYPE; } -static void map_pages(void *map, - uint64_t virt, - uint64_t phys, - enum page_type type, - size_t size) -{ - for (size_t offset = 0; offset < size; offset += page_size(1)) - { - map_page(map, virt + offset, phys + offset, type); - } -} - -#define KERNEL_SPACE_LOWER 0xffffffff80000000 -#define KERNEL_SPACE_UPPER 0xffffffffc0000000 +#define KERNEL_IMAGE_BASE 0xffffffff80000000 static void create_kernel_maps(Elf64_Ehdr *ehdr, void *base) { @@ -204,19 +126,19 @@ static void create_kernel_maps(Elf64_Ehdr *ehdr, void *base) } } - - // Create fractal mappings - uint64_t *lower_page_dir = get_page_table(system_page_map, - KERNEL_SPACE_LOWER, - 2); - uint64_t *upper_page_dir = get_page_table(system_page_map, - KERNEL_SPACE_UPPER, - 2); - - upper_page_dir[PAGE_TABLE_INDEX_MASK] = - (uint64_t)upper_page_dir|DATA_PAGE_TYPE; - upper_page_dir[PAGE_TABLE_INDEX_MASK - 1] = - (uint64_t)lower_page_dir|DATA_PAGE_TYPE; + // create a self-mapped page table at the very top of the virtual + // address space. this will give us 2MiB - 4KiB of virtual space to work + // with beginning at -2MiB . + // + // this is where any temporary mappings will be set up + // including the boot data tables that will be passed into the kernel + // and also the temporary window that the kernel will continue to use + // + map_page( + system_page_map, + -1ULL, + (uint64_t)get_page_table(system_page_map, -1ULL, 1), + DATA_PAGE_TYPE); } static void collect_boot_data(void) @@ -343,6 +265,9 @@ static EFI_STATUS enter_kernel(Elf64_Ehdr *ehdr) set_page_map(system_page_map); + while (true) + __asm__("cli;hlt"); + k_boot_data = (struct kc_boot_data *)object_space_base; k_boot_data->object_space.base = sizeof(*k_boot_data) + (char *)object_space_base; @@ -351,7 +276,7 @@ static EFI_STATUS enter_kernel(Elf64_Ehdr *ehdr) convert_memory_map(); kc_entry_func kernel_entry = (kc_entry_func) - (KERNEL_SPACE_LOWER + ehdr->e_entry); + (KERNEL_IMAGE_BASE + ehdr->e_entry); kernel_entry(k_boot_data); return status; @@ -391,10 +316,10 @@ EFI_STATUS kc_main(struct efi_loader_interface *interface) Elf64_Ehdr *ehdr = (Elf64_Ehdr *)kernel_image.buffer_base; plog(L"mapping kernel pages\r\n"); - create_kernel_maps(ehdr, (void *)KERNEL_SPACE_LOWER); + create_kernel_maps(ehdr, (void *)KERNEL_IMAGE_BASE); object_space_base = (void *)(page_align(kernel_image.buffer_size,1) + - (char *)KERNEL_SPACE_LOWER); + (char *)KERNEL_IMAGE_BASE); // add a tail of 64KiB to the kernel image uint64_t object_space_end = (uintptr_t)object_space_base + diff --git a/kc/boot/loader_paging.c b/kc/boot/loader_paging.c new file mode 100644 index 0000000..8ab40c3 --- /dev/null +++ b/kc/boot/loader_paging.c @@ -0,0 +1,69 @@ +#include "loader_paging.h" + +uint64_t *get_page_map(void) +{ + uint64_t map; + __asm__("mov %%cr3, %0" : "=r"(map)); + return (uint64_t *)(page_address(map, 1)); +} + +void set_page_map(uint64_t *map) +{ + __asm__ volatile + ( + "pushf\n\t" + "cli\n\t" + "mov %0, %%cr3\n\t" + "popf\n\t" + : + : "r"(map)); +} + +uint64_t *get_page_table(uint64_t *map, uint64_t virt, int level) +{ + if ((level < 1) || (level > PAGE_MAP_LEVELS)) + { + return NULL; + } + + for (int i = PAGE_MAP_LEVELS; i > level; i--) + { + if (!map[pte_index(virt, i)]) + { + map[pte_index(virt, i)] = + (uint64_t)new_page_table()|PAGE_PR|PAGE_WR; + } + + map = (uint64_t *)page_address(map[pte_index(virt, i)], 1); + } + + return map; +} + +uint64_t *get_page_entry(uint64_t *map, uint64_t virt) +{ + int level = 1; + uint64_t *table = get_page_table(map, virt, level); + return &table[pte_index(virt, level)]; +} + +void map_page(void *map, + uint64_t virt, + uint64_t phys, + enum page_type type) +{ + *get_page_entry(map, virt) = phys | type; +} + +void map_pages(void *map, + uint64_t virt, + uint64_t phys, + enum page_type type, + size_t size) +{ + for (size_t offset = 0; offset < size; offset += page_size(1)) + { + map_page(map, virt + offset, phys + offset, type); + } +} + diff --git a/kc/boot/loader_paging.h b/kc/boot/loader_paging.h new file mode 100644 index 0000000..dc9df62 --- /dev/null +++ b/kc/boot/loader_paging.h @@ -0,0 +1,29 @@ +#pragma once + +#include <kernel/memory/paging.h> + +#include <stdint.h> + +enum page_type +{ + INVALID_PAGE_TYPE = 0x0, + CODE_PAGE_TYPE = PAGE_PR, + RODATA_PAGE_TYPE = PAGE_PR, + DATA_PAGE_TYPE = PAGE_PR|PAGE_WR +}; + +uint64_t *new_page_table(void); +uint64_t *get_page_map(void); +void set_page_map(uint64_t *map); +uint64_t *get_page_table(uint64_t *map, uint64_t virt, int level); +uint64_t *get_page_entry(uint64_t *map, uint64_t virt); +void map_page(void *map, + uint64_t virt, + uint64_t phys, + enum page_type type); +void map_pages(void *map, + uint64_t virt, + uint64_t phys, + enum page_type type, + size_t size); + |
