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);