diff options
Diffstat (limited to 'src/kernel/mem')
-rw-r--r-- | src/kernel/mem/virt.c | 160 | ||||
-rw-r--r-- | src/kernel/mem/virt.h | 12 |
2 files changed, 0 insertions, 172 deletions
diff --git a/src/kernel/mem/virt.c b/src/kernel/mem/virt.c deleted file mode 100644 index 1ac6fbc..0000000 --- a/src/kernel/mem/virt.c +++ /dev/null @@ -1,160 +0,0 @@ -/* Copies stuff between different pagedirs. Mostly a wrapper behind an old, - * bad interface. */ - -// TODO ensure the behaviour of kernel vs user fs on faults is the same - -#include <kernel/arch/generic.h> -#include <kernel/mem/virt.h> -#include <kernel/panic.h> -#include <kernel/proc.h> -#include <kernel/util.h> -#include <shared/mem.h> - -struct virt_iter { - void *frag; - size_t frag_len; - size_t prior; // sum of all prior frag_lens - bool error; - - void __user *_virt; - size_t _remaining; - Pagedir *_pages; - bool _user; - bool _writeable; -}; - -struct virt_cpy_error { // unused - bool read_fail, write_fail; -}; - -/* if pages == NULL, creates an iterator over physical memory. */ -static void virt_iter_new( - struct virt_iter *iter, void __user *virt, size_t length, - Pagedir *pages, bool user, bool writeable -); -static bool virt_iter_next(struct virt_iter *); -static size_t virt_cpy( - Pagedir *dest_pages, void __user *dest, - Pagedir *src_pages, const void __user *src, - size_t length, struct virt_cpy_error *err -); - - -static void -virt_iter_new( - struct virt_iter *iter, void __user *virt, size_t length, - Pagedir *pages, bool user, bool writeable -) { - iter->frag = NULL; - iter->frag_len = 0; - iter->prior = 0; - iter->error = false; - iter->_virt = virt; - iter->_remaining = length; - iter->_pages = pages; - iter->_user = user; - iter->_writeable = writeable; -} - -static 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 */ - - size_t partial = iter->_remaining; - iter->prior += iter->frag_len; - if (partial <= 0) return false; - - if (iter->_pages) { // if iterating over virtual memory - // don't cross page boundaries - size_t to_page = PAGE_SIZE - ((uintptr_t)iter->_virt & PAGE_MASK); - partial = min(partial, to_page); - - iter->frag = pagedir_virt2phys(iter->_pages, - iter->_virt, iter->_user, iter->_writeable); - - if (!iter->frag) { - iter->error = true; - return false; - } - } else { - // "iterate" over physical memory - // the double cast supresses the warning about changing address spaces - iter->frag = (void* __force)iter->_virt; - } - - iter->frag_len = partial; - iter->_remaining -= partial; - iter->_virt += partial; - return true; -} - -static size_t -virt_cpy( - Pagedir *dest_pages, void __user *dest, - Pagedir *src_pages, const void __user *src, - size_t length, struct virt_cpy_error *err -) { - struct virt_iter dest_iter, src_iter; - size_t total = 0, partial; - - virt_iter_new(&dest_iter, dest, length, dest_pages, true, true); - virt_iter_new( &src_iter, (userptr_t)src, length, src_pages, true, false); - dest_iter.frag_len = 0; - src_iter.frag_len = 0; - - for (;;) { - if (dest_iter.frag_len <= 0 && !virt_iter_next(&dest_iter)) break; - if ( src_iter.frag_len <= 0 && !virt_iter_next( &src_iter)) break; - - partial = min(src_iter.frag_len, dest_iter.frag_len); - total += partial; - memcpy(dest_iter.frag, src_iter.frag, partial); - - dest_iter.frag_len -= partial; - dest_iter.frag += partial; - src_iter.frag_len -= partial; - src_iter.frag += partial; - } - - if (err) { - err->read_fail = src_iter.error; - err->write_fail = dest_iter.error; - } - if (src_iter.error || dest_iter.error) - assert(total != length); - else - assert(total == length); - return total; -} - -size_t -pcpy_to(Proc *p, __user void *dst, const void *src, size_t len) -{ - assert(p); - if (!p->pages) return 0; - return virt_cpy(p->pages, dst, NULL, (__user void*)src, len, NULL); -} - -size_t -pcpy_from(Proc *p, void *dst, const __user void *src, size_t len) -{ - assert(p); - if (!p->pages) return 0; - return virt_cpy(NULL, (__user void*)dst, p->pages, src, len, NULL); -} - -size_t -pcpy_bi( - Proc *dstp, __user void *dst, - Proc *srcp, const __user void *src, - size_t len -) { - assert(dstp && srcp); - if (!dstp->pages) return 0; - if (!srcp->pages) return 0; - return virt_cpy(dstp->pages, dst, srcp->pages, src, len, NULL); -} diff --git a/src/kernel/mem/virt.h b/src/kernel/mem/virt.h deleted file mode 100644 index 7c9380e..0000000 --- a/src/kernel/mem/virt.h +++ /dev/null @@ -1,12 +0,0 @@ -// move this to proc.h, maybe? -#pragma once -#include <kernel/types.h> -#include <stddef.h> - -size_t pcpy_to(Proc *p, __user void *dst, const void *src, size_t len); -size_t pcpy_from(Proc *p, void *dst, const __user void *src, size_t len); -size_t pcpy_bi( - Proc *dstp, __user void *dst, - Proc *srcp, const __user void *src, - size_t len -); |