Add page directory cloning, beginning of multitasking
diff --git a/src/kernel/Jmk b/src/kernel/Jmk
index 0cf5de3..5774274 100644
--- a/src/kernel/Jmk
+++ b/src/kernel/Jmk
@@ -35,7 +35,8 @@
 			vfs.o \
 			multiboot.o \
 			vfs_initrd.o \
-			syscall.o
+			syscall.o \
+			task.o
 
 type(custom_link)
 
diff --git a/src/kernel/alloc.c b/src/kernel/alloc.c
index 0268928..e3c85b1 100644
--- a/src/kernel/alloc.c
+++ b/src/kernel/alloc.c
@@ -7,7 +7,7 @@
 
 extern uint end;
 static size_t palloc_base = (size_t)&end;
-static size_t malloc_base = (size_t)&end + 0x2000;
+static size_t malloc_base = (size_t)&end + 0x8000;
 
 #define HEADER_SIZE sizeof(struct heap_alloc_header)
 #define FOOTER_SIZE sizeof(struct heap_alloc_footer)
@@ -24,11 +24,18 @@
 
 	if (phys)
 	{
-		*phys = (void *)palloc_base;
+		*phys = (void *)VIRT_TO_PHYS((void *)palloc_base);
 	}
 
 	size_t addr = palloc_base;
 	palloc_base += size;
+
+	if (palloc_base >= malloc_base)
+	{
+		kpanic("fatal error: placeholder kmalloc has overrun malloc() memory,"
+			   " cannot recover.");
+	}
+
 	return (void *)addr;
 }
 
diff --git a/src/kernel/kint.h b/src/kernel/kint.h
index d892f88..f70b22f 100644
--- a/src/kernel/kint.h
+++ b/src/kernel/kint.h
@@ -18,3 +18,6 @@
 #define NULL 0
 #define MIN(a, b) ((a)>(b)?(b):(a))
 #define MAX(a, b) ((a)>(b)?(a):(b))
+
+// Coerce into 1 or 0
+#define BOOL(a) (!(!(a)))
diff --git a/src/kernel/paging.h b/src/kernel/paging.h
index 8128d43..d7121a6 100644
--- a/src/kernel/paging.h
+++ b/src/kernel/paging.h
@@ -4,7 +4,7 @@
 #include "registers.h"
 
 #define VIRT_TO_PHYS(virt) ((uint)(virt) - 0xC0000000)
-#define PHYS_TO_VIRT(phys) ((uint)(phys) + 0xC0000000)
+#define PHYS_TO_VIRT(phys) ((void *)(phys) + 0xC0000000)
 #define KERNEL_VIRTUAL_BASE 0xC0000000
 #define KERNEL_PAGE_NUMBER (KERNEL_VIRTUAL_BASE >> 22)
 
diff --git a/src/kernel/task.c b/src/kernel/task.c
new file mode 100644
index 0000000..b4c1b33
--- /dev/null
+++ b/src/kernel/task.c
@@ -0,0 +1,61 @@
+#include "task.h"
+#include "alloc.h"
+#include "io.h"
+#include "paging.h"
+
+uint clone_page_table(uint table)
+{
+	// is this table a 4mb mapping OR is it not mapped?
+	// See Intel manual volume 3 figure 4-4.
+
+	if (table & 1 << 7 || !(table & 1))
+	{
+		// if so, return as is, 4mb mappings only used by kernel and should
+		// be mapped to the same location
+		return table;
+	}
+	else
+	{
+		// else, look for the used pages in this table, copy them to a new
+		// frame, and store them in a new table, then return that table
+		// TODO: add copy on write
+
+		uint new_p;
+		uint *new = kmalloc_ap(sizeof(uint[1024]), (void **)&new_p);
+
+		// We don't care about the lower 12 bits, just want the address
+		uint *old_virt = PHYS_TO_VIRT((uint *)(table ^ 0xfff));
+
+		for (int i = 0; i < 1024; i++)
+		{
+			if (old_virt[i] & 1)
+			{
+				// If mapped
+
+				// again, don't care about bottom 12 bits
+				uchar *old_page = PHYS_TO_VIRT(old_virt[i] ^ 0xfff);
+
+				alloc_frame(&new[i], BOOL(old_virt[i] & 1 << 2),
+							BOOL(old_virt[i] & 1 << 1));
+
+				uchar *new_page = PHYS_TO_VIRT(new[i] ^ 0xfff);
+				memcpy(new_page, old_page, 0x1000);
+			}
+		}
+
+		return new_p | (table & 0xfff); // same lower 12 bits
+	}
+}
+
+uint *clone_page_directory(uint *dir)
+{
+	uint new_p;
+	uint *new = kmalloc_ap(sizeof(uint[1024]), (void **)&new_p);
+
+	for (int i = 0; i < 1024; i++)
+	{
+		new[i] = clone_page_table(dir[i]);
+	}
+
+	return new;
+}
diff --git a/src/kernel/task.h b/src/kernel/task.h
new file mode 100644
index 0000000..0905a5f
--- /dev/null
+++ b/src/kernel/task.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "kint.h"
+
+// NOTE: uses kmalloc_a for now, this is bad because we will probably
+// run out of memory pretty quick, but malloc() doesn't support alignment
+// yet, so here we are.
+// dir is the VIRTUAL address, return is also virtual
+uint *clone_page_directory(uint *dir);
+// here, both return and argument are PHYSICAL
+uint clone_page_table(uint table);