From 1bf901c803bff3393d0cc9dfe76fc9f025cecb1c Mon Sep 17 00:00:00 2001
From: dzwdz
Date: Sun, 12 Sep 2021 14:59:47 +0200
Subject: barebones `memflag()` implementation - letting the user allocate
 pages

---
 src/init/main.c       |  6 ++++++
 src/init/syscalls.c   |  4 ++++
 src/kernel/syscalls.c | 22 ++++++++++++++++++++++
 src/shared/flags.h    |  5 +++++
 src/shared/syscalls.h |  4 ++++
 5 files changed, 41 insertions(+)
 create mode 100644 src/shared/flags.h

(limited to 'src')

diff --git a/src/init/main.c b/src/init/main.c
index 06e59a2..dc5a975 100644
--- a/src/init/main.c
+++ b/src/init/main.c
@@ -1,4 +1,5 @@
 #include <init/types.h>
+#include <shared/flags.h>
 #include <shared/syscalls.h>
 #include <stdint.h>
 
@@ -8,6 +9,8 @@
 __attribute__((section("text")))
 int tty_fd;
 
+int test;
+
 void fs_test(void);
 
 int main(void) {
@@ -16,6 +19,9 @@ int main(void) {
 		_syscall_exit(argify("couldn't open tty"));
 	log(" opened /tty ");
 
+	_syscall_memflag(&test, sizeof(int), MEMFLAG_PRESENT);
+	test = 0; // would cause a pagefault without the memflag call
+
 	fs_test();
 	_syscall_exit(argify("my job here is done."));
 }
diff --git a/src/init/syscalls.c b/src/init/syscalls.c
index e63f911..8d5ecf2 100644
--- a/src/init/syscalls.c
+++ b/src/init/syscalls.c
@@ -44,3 +44,7 @@ handle_t _syscall_fs_create(handle_t __user *back) {
 int _syscall_fs_wait(handle_t back, char __user *buf, int __user *len) {
 	return _syscall(_SYSCALL_FS_WAIT, back, (int)buf, (int)len);
 }
+
+int _syscall_memflag(void __user *addr, size_t len, int flags) {
+	return _syscall(_SYSCALL_MEMFLAG, (int)addr, len, flags);
+}
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index 21c1b72..1180197 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -5,6 +5,7 @@
 #include <kernel/proc.h>
 #include <kernel/types.h>
 #include <kernel/vfs/path.h>
+#include <shared/flags.h>
 #include <shared/syscalls.h>
 #include <stdint.h>
 
@@ -221,6 +222,25 @@ int _syscall_fs_wait(handle_t back, char __user *buf, int __user *len) {
 	}
 }
 
+int _syscall_memflag(void __user *addr, size_t len, int flags) {
+	userptr_t goal = addr + len;
+	struct pagedir *pages = process_current->pages;
+	if (flags != MEMFLAG_PRESENT) panic(); // currently only allocation is implemented
+
+	addr = (userptr_t)((int)addr & ~PAGE_MASK); // align to page boundary
+	for (; addr < goal; addr += PAGE_SIZE) {
+		if (pagedir_virt2phys(pages, addr, false, false)) {
+			// allocated page, currently a no-op
+			// if you'll be changing this - remember to check if the pages are owned by the kernel!
+		} else {
+			// allocate the new pages
+			pagedir_map(pages, addr, page_alloc(1), true, true);
+		}
+	}
+
+	return -1;
+}
+
 int syscall_handler(int num, int a, int b, int c) {
 	switch (num) {
 		case _SYSCALL_EXIT:
@@ -243,6 +263,8 @@ int syscall_handler(int num, int a, int b, int c) {
 			return _syscall_fs_create((userptr_t)a);
 		case _SYSCALL_FS_WAIT:
 			return _syscall_fs_wait(a, (userptr_t)b, (userptr_t)c);
+		case _SYSCALL_MEMFLAG:
+			return _syscall_memflag((userptr_t)a, b, c);
 		default:
 			tty_const("unknown syscall ");
 			panic();
diff --git a/src/shared/flags.h b/src/shared/flags.h
new file mode 100644
index 0000000..9ab8d9d
--- /dev/null
+++ b/src/shared/flags.h
@@ -0,0 +1,5 @@
+#pragma once
+
+enum {
+	MEMFLAG_PRESENT = 1 << 0,
+};
diff --git a/src/shared/syscalls.h b/src/shared/syscalls.h
index a746ade..d96c8a7 100644
--- a/src/shared/syscalls.h
+++ b/src/shared/syscalls.h
@@ -22,6 +22,8 @@ enum {
 
 	_SYSCALL_FS_CREATE,
 	_SYSCALL_FS_WAIT,
+
+	_SYSCALL_MEMFLAG,
 };
 
 /** Kills the current process.
@@ -53,3 +55,5 @@ int _syscall_close(handle_t);
 handle_t _syscall_fs_create(handle_t __user *back);
 
 int _syscall_fs_wait(handle_t back, char __user *buf, int __user *len);
+
+int _syscall_memflag(void __user *addr, size_t len, int flags);
-- 
cgit v1.2.3