From a0a4acb002f051d8a964659cb7aa9cd51740266a Mon Sep 17 00:00:00 2001
From: dzwdz
Date: Wed, 11 Aug 2021 17:50:57 +0000
Subject: abstract out iterating over virtual memory

most syscalls will have to do this to copy memory around or whatever.
it's pretty ugly too, but i can't come up with a better abstraction...
---
 src/kernel/mem.c      | 43 +++++++++++++++++++++++++++++++++++++++++++
 src/kernel/mem.h      | 21 +++++++++++++++++++++
 src/kernel/syscalls.c | 29 ++++++++---------------------
 3 files changed, 72 insertions(+), 21 deletions(-)

(limited to 'src')

diff --git a/src/kernel/mem.c b/src/kernel/mem.c
index 19a10a9..9ba0231 100644
--- a/src/kernel/mem.c
+++ b/src/kernel/mem.c
@@ -35,3 +35,46 @@ void *kmalloc(size_t len) {
 void kfree(void *ptr) {
 	// unimplemented
 }
+
+
+// TODO move to some shared file in kernel/arch/
+void virt_iter_new(
+		struct virt_iter *iter, void *virt, size_t length,
+		struct pagedir *pages, bool user, bool writeable)
+{
+	iter->frag       = 0;
+	iter->error      = false;
+	iter->_virt      = virt;
+	iter->_remaining = length;
+	iter->_pages     = pages;
+	iter->_user      = user;
+	iter->_writeable = writeable;
+}
+
+bool virt_iter_next(struct virt_iter *iter) {
+	/* note: While i'm pretty sure that this should always work, this
+	 * was only tested in cases where the pages were consecutive both in
+	 * virtual and physical memory, which might not always be the case.
+	 * TODO test this */
+
+	uintptr_t virt = (uintptr_t) iter->_virt;
+	size_t partial = iter->_remaining;
+	if (partial <= 0) return false;
+
+	// don't read past the page
+	if ((virt & PAGE_MASK) + partial > PAGE_SIZE)
+		partial = PAGE_SIZE - (virt & PAGE_MASK);
+
+	iter->frag = pagedir_virt2phys(iter->_pages,
+			iter->_virt, iter->_user, iter->_writeable);
+
+	if (iter->frag == 0) {
+		iter->error = true;
+		return false;
+	}
+
+	iter->frag_len    = partial;
+	iter->_remaining -= partial;
+	iter->_virt      += partial;
+	return true;
+}
diff --git a/src/kernel/mem.h b/src/kernel/mem.h
index b17ba30..78de8db 100644
--- a/src/kernel/mem.h
+++ b/src/kernel/mem.h
@@ -1,4 +1,5 @@
 #pragma once
+#include <kernel/arch/generic.h>
 #include <kernel/main.h>
 #include <stddef.h>
 
@@ -12,3 +13,23 @@ void page_free(void *first, size_t pages);
 
 void *kmalloc(size_t len);
 void kfree(void *ptr);
+
+
+// used for iterating through some part of a process' memory
+struct virt_iter {
+	void *frag;
+	size_t frag_len;
+	bool error;
+
+	void *_virt;
+	size_t _remaining;
+	struct pagedir *_pages;
+	bool _user;
+	bool _writeable;
+};
+
+void virt_iter_new(
+		struct virt_iter *iter, void *virt, size_t length,
+		struct pagedir *pages, bool user, bool writeable);
+
+bool virt_iter_next(struct virt_iter *);
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index 7234e10..7d0f81f 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -1,4 +1,5 @@
 #include <kernel/arch/generic.h>
+#include <kernel/mem.h>
 #include <kernel/panic.h>
 #include <kernel/proc.h>
 #include <kernel/syscalls.h>
@@ -22,29 +23,15 @@ int _syscall_fork() {
 }
 
 int _syscall_debuglog(const char *msg, size_t len) {
-	struct pagedir *pages = process_current->pages;
-	size_t remaining = len;
+	struct virt_iter iter;
+	size_t written;
 
-	while (remaining > 0) {
-		/* note: While i'm pretty sure that this should always work, this
-		 * was only tested in cases where the pages were consecutive both in
-		 * virtual and physical memory, which might not always be the case.
-		 * TODO test this */
-
-		void *phys = pagedir_virt2phys(pages, msg, true, false);
-		size_t partial = remaining;
-
-		// don't read past the page
-		if (((uintptr_t)msg & PAGE_MASK) + remaining > PAGE_SIZE)
-			partial = PAGE_SIZE - ((uintptr_t)msg & PAGE_MASK);
-
-		tty_write(phys, partial);
-
-		remaining -= partial;
-		msg       += partial;
+	virt_iter_new(&iter, msg, len, process_current->pages, true, false);
+	while (virt_iter_next(&iter)) {
+		tty_write(iter.frag, iter.frag_len);
+		written += iter.frag_len;
 	}
-
-	return len;
+	return written;
 }
 
 int syscall_handler(int num, int a, int b, int c) {
-- 
cgit v1.2.3