summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/kernel/mem.c43
-rw-r--r--src/kernel/mem.h21
-rw-r--r--src/kernel/syscalls.c29
3 files changed, 72 insertions, 21 deletions
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) {