BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / commit / 27ddc7fe7d977cb1c3a1cfff78dd1e4853bf5ad6 / memory / paging.c

// Related

Nucleus

Barry Kernel heap + paging functions 27ddc7f (3 years, 3 months ago)
diff --git a/memory/paging.c b/memory/paging.c
index b4f505e..cd6deb5 100644
--- a/memory/paging.c
+++ b/memory/paging.c
@@ -10,6 +10,8 @@
 #include <nucleus/memory.h>
 #include "paging.h"
 
+void copy_page_frame(uintptr_t src, uintptr_t dest);
+
 /* Switch page directory */
 static void
 switch_dir(page_dir_t dir)
@@ -33,6 +35,60 @@ set_page(uintptr_t vaddr, page_t page)
 	mappings[address] = page;
 }
 
+/* Clone an entire page directory */
+page_dir_t
+clone_dir(void)
+{
+	page_table_t *oldTables = (void *) 0xFFFFF000;
+	page_table_t *newTables = (void *) 0xFFFFE000;
+	page_t *oldTable, *newTable;
+	page_dir_t dir = alloc_frame();
+	uint16_t tbl, pg;
+
+	/* Temporarily link new paging structures into current directory */
+	page_table_t restore = oldTables[1022];
+	oldTables[1022] = dir | PDE_PRESENT | PDE_WRITE;
+	flush_tlb((uintptr_t) newTables);
+
+	/* Iterate tables */
+	for (tbl = 0; tbl < 1022; tbl++) {
+		if (!(oldTables[tbl] & PDE_PRESENT))
+			continue;
+
+
+		/* Link kernel tables */
+		if (tbl < 2 || tbl >= 1008) {
+			newTables[tbl] = oldTables[tbl];
+			continue;
+		}
+
+		/* Copy everything else */
+		newTables[tbl] = alloc_frame() | PAGE_ATTR(oldTables[tbl]);
+		oldTable = (page_t *) 0xFFC00000 + (tbl * 1024);
+		newTable = (page_t *) 0xFF800000 + (tbl * 1024);
+		flush_tlb((uintptr_t) newTable);
+		for (pg = 0; pg < 1024; pg++) {
+			if (!(oldTable[pg] & PTE_PRESENT)) {
+				newTable[pg] = 0;
+				continue;
+			}
+
+			/* Copy page frame content */
+			newTable[pg] = alloc_frame() | PAGE_ATTR(oldTable[pg]);
+			flush_tlb(((tbl * 1024) + pg) << 12);
+			copy_page_frame(PAGE_ADDR(oldTable[pg]),
+			                PAGE_ADDR(newTable[pg]));
+		}
+	}
+	newTables[1023] = oldTables[1022];
+
+	/* Unlink paging structures from current directory */
+	oldTables[1022] = restore;
+	flush_tlb((uintptr_t) newTables);
+
+	return dir;
+}
+
 /* Initialise paging */
 void
 init_paging(void)