diff options
-rw-r--r-- | src/kernel/mem.c | 43 | ||||
-rw-r--r-- | src/kernel/mem.h | 21 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 29 |
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) { |