summaryrefslogtreecommitdiff
path: root/kc
diff options
context:
space:
mode:
authorAda Christine <adachristine18@gmail.com>2022-02-21 16:38:41 +0000
committerAda Christine <adachristine18@gmail.com>2022-02-21 16:38:41 +0000
commit203776e1e0b27786775b01a8bcfdd14b3e3d1816 (patch)
tree8a48e45d996b06b532e9828575e14d1d8ffece92 /kc
parent6002ec7d841d91d85cc55733c539594c97fc2e30 (diff)
split out paging functions
Diffstat (limited to 'kc')
-rw-r--r--kc/boot/Makefile2
-rw-r--r--kc/boot/kc_main.c121
-rw-r--r--kc/boot/loader_paging.c69
-rw-r--r--kc/boot/loader_paging.h29
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);
+