summaryrefslogtreecommitdiff
path: root/src/kernel/mem
diff options
context:
space:
mode:
authordzwdz2023-01-25 01:02:04 +0100
committerdzwdz2023-01-25 01:04:49 +0100
commit2a2fc4dffe0117ce874a6cf1dcc34321ed8add77 (patch)
treeaf1e24f72241dbbff97797b9e186f7d27b5b54b4 /src/kernel/mem
parent52e7fe3c679469032e77a5ca4adf19618ba1201b (diff)
kernel/virt: replace the virt_cpy api with a more foolproof one
Diffstat (limited to 'src/kernel/mem')
-rw-r--r--src/kernel/mem/virt.c84
-rw-r--r--src/kernel/mem/virt.h52
2 files changed, 85 insertions, 51 deletions
diff --git a/src/kernel/mem/virt.c b/src/kernel/mem/virt.c
index bff4b5e..8bf5e69 100644
--- a/src/kernel/mem/virt.c
+++ b/src/kernel/mem/virt.c
@@ -1,13 +1,50 @@
+/* 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>
-void virt_iter_new(
- struct virt_iter *iter, void __user *virt, size_t length,
- struct pagedir *pages, bool user, bool writeable)
-{
+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;
+ struct 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,
+ struct pagedir *pages, bool user, bool writeable
+);
+static bool virt_iter_next(struct virt_iter *);
+static size_t virt_cpy(
+ struct pagedir *dest_pages, void __user *dest,
+ struct 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,
+ struct pagedir *pages, bool user, bool writeable
+) {
iter->frag = NULL;
iter->frag_len = 0;
iter->prior = 0;
@@ -19,7 +56,9 @@ void virt_iter_new(
iter->_writeable = writeable;
}
-bool virt_iter_next(struct virt_iter *iter) {
+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.
@@ -53,11 +92,12 @@ bool virt_iter_next(struct virt_iter *iter) {
return true;
}
-size_t virt_cpy(
+static size_t
+virt_cpy(
struct pagedir *dest_pages, void __user *dest,
struct pagedir *src_pages, const void __user *src,
- size_t length, struct virt_cpy_error *err)
-{
+ size_t length, struct virt_cpy_error *err
+) {
struct virt_iter dest_iter, src_iter;
size_t total = 0, partial;
@@ -90,3 +130,31 @@ size_t virt_cpy(
assert(total == length);
return total;
}
+
+size_t
+pcpy_to(struct process *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(struct process *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(
+ struct process *dstp, __user void *dst,
+ struct process *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
index 1f9ef14..fc35078 100644
--- a/src/kernel/mem/virt.h
+++ b/src/kernel/mem/virt.h
@@ -1,48 +1,14 @@
-/* contains utilities for interacting with virtual memory */
+// move this to proc.h, maybe?
#pragma once
#include <camellia/types.h>
-#include <kernel/mem/alloc.h>
-#include <stdbool.h>
#include <stddef.h>
-struct virt_iter {
- void *frag;
- size_t frag_len;
- size_t prior; // sum of all prior frag_lens
- bool error;
+struct process;
- void __user *_virt;
- size_t _remaining;
- struct pagedir *_pages;
- bool _user;
- bool _writeable;
-};
-
-struct virt_cpy_error {
- bool read_fail, write_fail;
-};
-
-/* if pages == NULL, create an iterator over physical memory. */
-void virt_iter_new(
- struct virt_iter *iter, void __user *virt, size_t length,
- struct pagedir *pages, bool user, bool writeable);
-
-bool virt_iter_next(struct virt_iter *);
-
-size_t virt_cpy(
- struct pagedir *dest_pages, void __user *dest,
- struct pagedir *src_pages, const void __user *src,
- size_t length, struct virt_cpy_error *err);
-
-
-/* copies to virtual memory, returns true on success */
-static inline bool virt_cpy_to(struct pagedir *dest_pages,
- void __user *dest, const void *src, size_t length) {
- return length == virt_cpy(dest_pages, dest, NULL, (userptr_t)src, length, NULL);
-}
-
-/* copies from virtual memory, returns true on success */
-static inline bool virt_cpy_from(struct pagedir *src_pages,
- void *dest, const void __user *src, size_t length) {
- return length == virt_cpy(NULL, (userptr_t)dest, src_pages, src, length, NULL);
-}
+size_t pcpy_to(struct process *p, __user void *dst, const void *src, size_t len);
+size_t pcpy_from(struct process *p, void *dst, const __user void *src, size_t len);
+size_t pcpy_bi(
+ struct process *dstp, __user void *dst,
+ struct process *srcp, const __user void *src,
+ size_t len
+);