diff options
author | dzwdz | 2021-09-05 18:55:32 +0200 |
---|---|---|
committer | dzwdz | 2021-09-05 18:55:32 +0200 |
commit | 0b2b263060907e8bf732c1d27c66b7358af01e9f (patch) | |
tree | 321e459503ed2694126b2556e3064f95006c0148 /src/kernel | |
parent | 838b142b7374150df63ec02b02377c114a14b314 (diff) |
make virt_iter support iterating over physical memory too
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/mem/virt.c | 22 | ||||
-rw-r--r-- | src/kernel/mem/virt.h | 1 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 30 |
3 files changed, 29 insertions, 24 deletions
diff --git a/src/kernel/mem/virt.c b/src/kernel/mem/virt.c index 2990668..beeb54f 100644 --- a/src/kernel/mem/virt.c +++ b/src/kernel/mem/virt.c @@ -23,21 +23,25 @@ bool virt_iter_next(struct virt_iter *iter) { * virtual and physical memory, which might not always be the case. * TODO test this */ - user_ptr virt = iter->_virt; size_t partial = iter->_remaining; iter->prior += iter->frag_len; if (partial <= 0) return false; - // don't read past the page - if ((virt & PAGE_MASK) + partial > PAGE_SIZE) - partial = PAGE_SIZE - (virt & PAGE_MASK); + if (iter->_pages) { // if iterating over virtual memory + // don't read past the page + if ((iter->_virt & PAGE_MASK) + partial > PAGE_SIZE) + partial = PAGE_SIZE - (iter->_virt & PAGE_MASK); - iter->frag = pagedir_virt2phys(iter->_pages, - iter->_virt, iter->_user, iter->_writeable); + iter->frag = pagedir_virt2phys(iter->_pages, + iter->_virt, iter->_user, iter->_writeable); - if (iter->frag == 0) { - iter->error = true; - return false; + if (iter->frag == 0) { + iter->error = true; + return false; + } + } else { + // "iterate" over physical memory + iter->frag = iter->_virt; } iter->frag_len = partial; diff --git a/src/kernel/mem/virt.h b/src/kernel/mem/virt.h index 98a7a16..e87a9fe 100644 --- a/src/kernel/mem/virt.h +++ b/src/kernel/mem/virt.h @@ -17,6 +17,7 @@ struct virt_iter { bool _writeable; }; +/* if pages == NULL, create an iterator over physical memory. */ void virt_iter_new( struct virt_iter *iter, user_ptr virt, size_t length, struct pagedir *pages, bool user, bool writeable); diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 416c815..2174791 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -68,36 +68,37 @@ int _syscall_fork(void) { } handle_t _syscall_open(const user_ptr path, int len) { - struct virt_iter iter; struct vfs_mount *mount; - static char buffer[PATH_MAX]; // holds the path + static char path_buf[PATH_MAX]; - if (len > PATH_MAX) return -1; + if (len > PATH_MAX) + return -1; // fail if there are no handles left if (process_find_handle(process_current) < 0) return -1; // copy the path to the kernel - virt_iter_new(&iter, path, len, process_current->pages, true, false); - while (virt_iter_next(&iter)) - memcpy(buffer + iter.prior, iter.frag, iter.frag_len); - if (iter.error) return -1; + // note: the cast is necessary because the function usually accepts user_ptrs + // it can handle copies to physical memory too, though + if (!virt_user_cpy(NULL, (uintptr_t)path_buf, + process_current->pages, path, len)) + return -1; - len = path_simplify(buffer, buffer, len); + len = path_simplify(path_buf, path_buf, len); if (len < 0) return -1; - mount = vfs_mount_resolve(process_current->mount, buffer, len); + mount = vfs_mount_resolve(process_current->mount, path_buf, len); if (!mount) return -1; vfs_backend_dispatch(mount->backend, (struct vfs_op) { .type = VFSOP_OPEN, .open = { - .path = &buffer[mount->prefix_len], + .path = &path_buf[mount->prefix_len], .path_len = len - mount->prefix_len, } }); - // doesn't return. TODO mark as noreturn + // doesn't return } int _syscall_mount(handle_t handle, const user_ptr path, int len) { @@ -111,10 +112,9 @@ int _syscall_mount(handle_t handle, const user_ptr path, int len) { // copy the path to the kernel path_buf = kmalloc(len); - virt_iter_new(&iter, path, len, process_current->pages, true, false); - while (virt_iter_next(&iter)) - memcpy(path_buf + iter.prior, iter.frag, iter.frag_len); - if (iter.error) goto fail; + if (!virt_user_cpy(NULL, (uintptr_t)path_buf, + process_current->pages, path, len)) + goto fail; // simplify it len = path_simplify(path_buf, path_buf, len); |