summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/init.c')
-rw-r--r--arch/x86_64/init.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/arch/x86_64/init.c b/arch/x86_64/init.c
new file mode 100644
index 0000000..4ec7718
--- /dev/null
+++ b/arch/x86_64/init.c
@@ -0,0 +1,63 @@
+#include "init.h"
+#include "arch/x86_64/page.h"
+#include "device/processor.h"
+
+uintptr_t
+init_alloc_pageframe()
+{
+ objdir_entry_t *untyped_dir_entry = &_initDirectory.entries[INIT_OBJECT_UNTYPED_DIR];
+ objdir_t *untyped_dir = ko_entry_data(untyped_dir_entry);
+
+ /*Seek to the last member of untyped directory.*/
+ uint8_t lastmembi = 1;
+ for(; untyped_dir->entries[lastmembi].type == KO_MEMORY_UNTYPED; lastmembi++);
+ objdir_entry_t *lastmemb = &untyped_dir->entries[lastmembi];
+
+ objdir_entry_t pageframe;
+ ko_untyped_split(lastmemb, &pageframe, 0x1000);
+ return pageframe.data;
+}
+
+void
+init_map_pageframe(uintptr_t pptr, uintptr_t vptr, uint8_t pflags)
+{
+ uint64_t pathval;
+ uint16_t *path = (uint16_t*)&pathval;
+ pml4_get_path(vptr, 4, path);
+
+ processor_t *proc = processor_current();
+ pmle_t *pml4 = pptr_tovirt_ident(proc->pdir);
+
+ pmle_t *pmld = pml4;
+ for(uint8_t d = 0; d < 3; d++) {
+ uint16_t pmli = path[d];
+ pmle_t *pmle = &pmld[pmli];
+ if(!pmle->p) {
+ pmle->value = init_alloc_pageframe() | PAGE_PRESENT | PAGE_RW | PAGE_US;
+ }
+ pmld = pptr_tovirt_ident(pmle->paddr << 12);
+ }
+ pmld[path[3]].value = pptr | pflags;
+ __asm__ volatile("invlpg (%0)":: "r"(vptr): "memory");
+}
+
+void
+init_ensure_page(uintptr_t vptr, uint8_t pflags)
+{
+ uint64_t pathval;
+ uint16_t *path = (uint16_t*)&pathval;
+ pml4_get_path(vptr, 4, path);
+
+ processor_t *proc = processor_current();
+ pmle_t *pml4 = pptr_tovirt_ident(proc->pdir);
+
+ pmle_t *pmld = pml4, *pmle;
+ for(uint8_t d = 0; d < 4; d++) {
+ uint16_t pmli = path[d];
+ pmle = &pmld[pmli];
+ if(!pmle->p) {
+ pmle->value = init_alloc_pageframe() | (d == 3 ? pflags : PAGE_PRESENT | PAGE_RW | PAGE_US);
+ }
+ pmld = pptr_tovirt_ident(pmle->paddr << 12);
+ }
+}