summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/memory
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/memory')
-rw-r--r--arch/x86_64/memory/koentry-ptr.c16
-rw-r--r--arch/x86_64/memory/page-mapping.c15
-rw-r--r--arch/x86_64/memory/page_directory.c119
-rw-r--r--arch/x86_64/memory/untyped_memory.c52
-rw-r--r--arch/x86_64/memory/untyped_retype_page.c38
5 files changed, 240 insertions, 0 deletions
diff --git a/arch/x86_64/memory/koentry-ptr.c b/arch/x86_64/memory/koentry-ptr.c
new file mode 100644
index 0000000..b32d4e7
--- /dev/null
+++ b/arch/x86_64/memory/koentry-ptr.c
@@ -0,0 +1,16 @@
+#include "memory.h"
+#include "arch/x86_64/page.h"
+#include <stdint.h>
+
+void*
+ko_entry_data(objdir_entry_t *entry)
+{
+ if((intmax_t)entry->data < 0) return (void*)entry->data;
+ return vmem_phys_tovirt(entry->data);
+}
+
+uintptr_t
+ko_data_toentry(uintptr_t vptr)
+{
+ return vmem_ident_tophys((void*)vptr);
+}
diff --git a/arch/x86_64/memory/page-mapping.c b/arch/x86_64/memory/page-mapping.c
new file mode 100644
index 0000000..0de5bfa
--- /dev/null
+++ b/arch/x86_64/memory/page-mapping.c
@@ -0,0 +1,15 @@
+#include "arch/x86_64/page-mapping.h"
+#include "arch/x86_64/page.h"
+#include <stddef.h>
+
+pmle_t*
+page_mapping_traverse(pmle_t *pml4, uint8_t depth, uint16_t *path)
+{
+ uint16_t pathi = path[0];
+
+ pmle_t *pmle = &pml4[pathi];
+ pmle_t *pmle_table = vmem_phys_tovirt(pmle->paddr << 12);
+ if(depth == 0) return pmle;
+ if(!pmle->p) return NULL;
+ return page_mapping_traverse(pmle_table, depth - 1, path + 1);
+}
diff --git a/arch/x86_64/memory/page_directory.c b/arch/x86_64/memory/page_directory.c
new file mode 100644
index 0000000..7030b05
--- /dev/null
+++ b/arch/x86_64/memory/page_directory.c
@@ -0,0 +1,119 @@
+#include "arch/x86_64/page.h"
+#include "arch/x86_64/object.h"
+#include "device/processor.h"
+#include "print.h"
+#include "memory.h"
+#include "object.h"
+#include "string.h"
+#include "jove.h"
+#include <stdint.h>
+
+physptr_t s_kpbase(void);
+
+#if defined(__limine__)
+
+#include "boot/limine/limine.h"
+static struct limine_kernel_address_request s_kaddr_req = {
+ .id = LIMINE_KERNEL_ADDRESS_REQUEST
+};
+
+physptr_t s_kpbase(void) { return s_kaddr_req.response->physical_base; }
+
+#endif
+
+physptr_t
+vmem_tophys_koff(virtptr_t v)
+{
+ return v - (physptr_t)&_kernel_start + s_kpbase();
+}
+
+#define IDENTITY_BASE 0xFFFF800000000000
+void*
+vmem_phys_tovirt(physptr_t p)
+{
+ return (void*)(p + IDENTITY_BASE);
+}
+
+uintptr_t vmem_ident_tophys(void *vptr)
+{
+ return ((uintptr_t)vptr) - IDENTITY_BASE;
+}
+
+void*
+pmle_get_page(pmle_t entry)
+{
+ uintptr_t pptr = entry.paddr << 12;
+ return vmem_phys_tovirt(pptr);
+}
+
+uint8_t
+pmle_level(pmle_t entry)
+{
+ return entry.osflg;
+}
+
+__attribute__((aligned(0x1000))) pmle_t s_kernel_pml4[512]; // Page L4
+__attribute__((aligned(0x1000))) pmle_t s_kernel_pml3[512]; // Page L3
+__attribute__((aligned(0x1000))) pmle_t s_kernel_pml2[512]; // Page directory
+__attribute__((aligned(0x1000))) pmle_t s_kernel_pml1[512]; // Page table
+
+__attribute__((aligned(0x1000))) pmle_t s_idmap_pml3[512];
+__attribute__((aligned(0x1000))) pmle_t s_idmap_pml2[512];
+
+void
+vmem_setup(void)
+{
+ memset(s_kernel_pml4, 0, 0x1000);
+ memset(s_kernel_pml3, 0, 0x1000);
+ memset(s_kernel_pml2, 0, 0x1000);
+ memset(s_kernel_pml1, 0, 0x1000);
+
+ memset(s_idmap_pml3, 0, 0x1000);
+ memset(s_idmap_pml2, 0, 0x1000);
+
+ virtptr_t kernel_start = (virtptr_t)&_kernel_start;
+ virtptr_t kernel_end = (virtptr_t)&_kernel_end;
+
+ size_t kernel_size = kernel_end - kernel_start;
+ size_t kernel_size_pages = (kernel_size / 0x1000) + 1;
+
+ physptr_t kernel_pml4_base = vmem_tophys_koff((virtptr_t)&s_kernel_pml4);
+ physptr_t kernel_pml3_base = vmem_tophys_koff((virtptr_t)&s_kernel_pml3);
+ physptr_t kernel_pml2_base = vmem_tophys_koff((virtptr_t)&s_kernel_pml2);
+ physptr_t kernel_pml1_base = vmem_tophys_koff((virtptr_t)&s_kernel_pml1);
+
+ physptr_t idmap_pml3_base = vmem_tophys_koff((virtptr_t)&s_idmap_pml3);
+ physptr_t idmap_pml2_base = vmem_tophys_koff((virtptr_t)&s_idmap_pml2);
+
+ processor_t *processor = processor_current();
+ processor->pdir = kernel_pml4_base;
+
+ //Map memory identity pages.
+ s_kernel_pml4[256].value = idmap_pml3_base | 2 | 1;
+ s_idmap_pml3[0].value = idmap_pml2_base | 2 | 1;
+ for(int i = 0; i < 512; i++) {
+ s_idmap_pml2[i].value = (i * 0x1000 * 512) | 0x80 | 2 | 1;
+ }
+
+ //Map the kernel to himem.
+
+ pmli_t kernel_pml3_i = PML_I_FOR_LAYER(kernel_start, 3);
+ pmli_t kernel_pml2_i = PML_I_FOR_LAYER(kernel_start, 2);
+ pmli_t kernel_pml1_ib = PML_I_FOR_LAYER(kernel_start, 1);
+ pmli_t kernel_pml1_ie = PML_I_FOR_LAYER(kernel_end, 1) + 1;
+
+ s_kernel_pml4[511].value = kernel_pml3_base | 2 | 1;
+ s_kernel_pml3[kernel_pml3_i].value = kernel_pml2_base | 2 | 1;
+ s_kernel_pml2[kernel_pml2_i].value = kernel_pml1_base | 2 | 1;
+ for(pmli_t i = kernel_pml1_ib; i < kernel_pml1_ie; i++) {
+ s_kernel_pml1[i].value = ((i * 0x1000) + s_kpbase()) | 3;
+ }
+
+ __asm__ volatile("mov %0, %%cr3":: "r"(kernel_pml4_base));
+
+ //Add page mapping object to init directory.
+ _initDirectory.entries[INIT_OBJECT_PAGEMAP] = (objdir_entry_t) {
+ .type = KO_MEMORY_MAPPING,
+ .data = kernel_pml4_base
+ };
+}
diff --git a/arch/x86_64/memory/untyped_memory.c b/arch/x86_64/memory/untyped_memory.c
new file mode 100644
index 0000000..bd3bc6d
--- /dev/null
+++ b/arch/x86_64/memory/untyped_memory.c
@@ -0,0 +1,52 @@
+#include "memory.h"
+#include "jove.h"
+#include "print.h"
+#include "arch/x86_64/object.h"
+#include "arch/x86_64/page.h"
+#include <stddef.h>
+
+static struct jove_ObjectDirectory s_untyped_dir = {
+ .self = { .type = KO_OBJECT_DIRECTORY, .data = 1 },
+};
+
+static void s_populate_tables();
+
+#if defined(__limine__)
+
+#include "boot/limine/limine.h"
+static volatile struct limine_memmap_request s_memmap_req = {
+ .id = LIMINE_MEMMAP_REQUEST,
+ .response = NULL
+};
+
+void
+pmem_setup(void)
+{
+ _initDirectory.entries[INIT_OBJECT_UNTYPED_DIR] = (objdir_entry_t) {
+ .type = KO_OBJECT_DIRECTORY,
+ .data = (uintptr_t)&s_untyped_dir
+ };
+
+ if(s_memmap_req.response == NULL) {
+ klogf("Failed to load physical memory map");
+ hcf();
+ }
+ struct limine_memmap_response *response = s_memmap_req.response;
+ for(size_t i = 0; i < response->entry_count; i++) {
+ struct limine_memmap_entry *entry = response->entries[i];
+ if(entry->type != LIMINE_MEMMAP_USABLE) continue;
+
+ size_t table_index = s_untyped_dir.self.data++;
+ uintmax_t *untyped_data = vmem_phys_tovirt(entry->base);
+ objdir_entry_t *table_entry = &s_untyped_dir.entries[table_index];
+
+ table_entry->type = KO_MEMORY_UNTYPED;
+ table_entry->data = (uintptr_t)entry->base;
+ *untyped_data = entry->length;
+
+ klogf("New untyped block %i at %p:%p\n",
+ table_index, entry->base, entry->length);
+ }
+}
+
+#endif
diff --git a/arch/x86_64/memory/untyped_retype_page.c b/arch/x86_64/memory/untyped_retype_page.c
new file mode 100644
index 0000000..32afe2c
--- /dev/null
+++ b/arch/x86_64/memory/untyped_retype_page.c
@@ -0,0 +1,38 @@
+#include "memory.h"
+#include "arch/x86_64/page.h"
+#include "print.h"
+#include <stddef.h>
+
+static int
+s_untyped_retype(
+ objdir_entry_t *untyped_entry,
+ size_t size,
+ size_t align,
+ void **dest)
+{
+ if(untyped_entry->type != KO_MEMORY_UNTYPED) return -1;
+ if((untyped_entry->data & (align - 1)) != 0) return -2; //EALIGN
+
+ uintptr_t *untyped_data = vmem_phys_tovirt(untyped_entry->data);
+ uintmax_t untyped_size = *untyped_data;
+
+ if(untyped_size <= size) {
+ return -3;
+ }
+
+ *untyped_data -= size;
+ *dest = (void*)(untyped_entry->data + untyped_size - size);
+
+ return 0;
+}
+
+int untyped_retype_page(objdir_entry_t *untyped_entry, void **dest)
+{
+ int r = s_untyped_retype(untyped_entry, 0x1000, 0x1000, dest);
+ if(r != 0) return r;
+
+ #ifdef DBG_MEM
+ klogf("Untyped block %p retyped to page at %p\n", untyped_entry->data, *dest);
+ #endif
+ return r;
+}