Nucleus
Barry Page functions + User memory functions 73145c0 (3 years, 3 months ago)
diff --git a/memory/fault.c b/memory/fault.c
index e8d66a7..dd7953f 100644
--- a/memory/fault.c
+++ b/memory/fault.c
@@ -16,8 +16,12 @@ early_page_fault_handler(struct InterruptFrame *frame, uint32_t err)
{
uintptr_t addr;
asm volatile("mov %%cr2, %0" : "=r" (addr));
+ uint8_t present = err & (1 << 0);
+ uint8_t write = err & (1 << 1);
+ uint8_t user = err & (1 << 2);
if (!PAGE_ADDR(addr))
panic("Null dereference @ %#.8x", frame->eip);
+ ASSERT(!present);
/* Allocate a page */
set_page(addr, alloc_frame() | PTE_PRESENT | PTE_WRITE | PTE_GLOBAL);
}
diff --git a/memory/frame.c b/memory/frame.c
index 8a868ea..c477121 100644
--- a/memory/frame.c
+++ b/memory/frame.c
@@ -100,7 +100,7 @@ find_frame(struct FrameRegion *region)
uintptr_t
alloc_frame(void)
{
- off_t idx;
+ int idx;
/* Walk the regions, first fit */
struct FrameRegion *region;
for (region = regions; region; region = region->next) {
diff --git a/memory/page.c b/memory/page.c
index 8dd07d8..6e1e67a 100644
--- a/memory/page.c
+++ b/memory/page.c
@@ -24,6 +24,7 @@ static void page_delete(Object *);
/* Page object type */
ObjectType pageType = {
+ .name = "PAGE",
.size = sizeof(Page),
.delete = page_delete,
};
@@ -49,16 +50,41 @@ compare_page_offset(void *object, void *data)
return 0;
}
+/* Create a new Page entry */
+Page *
+create_page(ObjectList *cache, page_t frame, off_t offset)
+{
+ Page *page = new(&pageType);
+ page->frame = frame;
+ page->offset = offset;
+ add(cache, page);
+ return page;
+}
+
/* Find a Page by offset in a cache */
Page *
find_page(ObjectList *cache, off_t offset)
{
- lock(cache);
struct FindData data = {
.offset = offset,
.result = NULL,
};
iterate(cache, compare_page_offset, &data);
- unlock(cache);
return data.result;
}
+
+/* Get the virtual address for the mapping of a page */
+void *
+map_page(Page *page)
+{
+ /*
+ * Since this x86 kernel doesn't keep all physical memory mapped into
+ * the virtual address space, the page needs to be mapped into memory.
+ * If more virtual memory was available (e.g. x86_64) all of physical
+ * memory could be mapped to an offset, and this function would just
+ * return (page->frame + offset);
+ */
+ set_page(0x7FF000, page->frame | PTE_PRESENT | PTE_WRITE);
+ flush_tlb(0x7FF000);
+ return (void *) 0x7FF000;
+}
diff --git a/memory/user.c b/memory/user.c
new file mode 100644
index 0000000..cdf4bcd
--- /dev/null
+++ b/memory/user.c
@@ -0,0 +1,24 @@
+/*
+ * This file handles safely getting data from userspace for the kernel. This is
+ * for security reasons to prevent the user from tricking a syscall into
+ * manipulating/leaking kernel data structures. User memory is defined as any
+ * address range that completely sits in a Virtual Memory Region.
+ */
+
+#include <nucleus/memory.h>
+
+/* Check if user has access to a region of memory */
+int
+verify_access(const void *addr, size_t len, int prot)
+{
+ /*
+ * This should iterate all memory regions to check if the address range
+ * fits inside one, if not then access should be denied. If a matching
+ * region is found, the prot parameter should be checked against the
+ * protection value for that region. If this function is called from
+ * the kernel directly, or the user did not pass an address or a length
+ * (NULL and 0, respectively), then it should just grant access
+ * immediately. This can be implemented when userspace is implemented.
+ */
+ return 1;
+}