summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordzwdz2023-01-25 01:02:04 +0100
committerdzwdz2023-01-25 01:04:49 +0100
commit2a2fc4dffe0117ce874a6cf1dcc34321ed8add77 (patch)
treeaf1e24f72241dbbff97797b9e186f7d27b5b54b4
parent52e7fe3c679469032e77a5ca4adf19618ba1201b (diff)
kernel/virt: replace the virt_cpy api with a more foolproof one
-rw-r--r--Makefile2
-rw-r--r--src/kernel/arch/amd64/driver/pata.c4
-rw-r--r--src/kernel/arch/amd64/driver/rtl8139.c18
-rw-r--r--src/kernel/arch/amd64/driver/serial.c15
-rw-r--r--src/kernel/arch/amd64/driver/util.c9
-rw-r--r--src/kernel/arch/amd64/driver/video.c7
-rw-r--r--src/kernel/arch/amd64/interrupts/isr.c6
-rw-r--r--src/kernel/mem/virt.c84
-rw-r--r--src/kernel/mem/virt.h52
-rw-r--r--src/kernel/pipe.c12
-rwxr-xr-xsrc/kernel/proc.c4
-rw-r--r--src/kernel/ring.c6
-rw-r--r--src/kernel/ring.h2
-rw-r--r--src/kernel/syscalls.c30
-rw-r--r--src/kernel/vfs/procfs.c11
-rw-r--r--src/kernel/vfs/request.c22
-rw-r--r--src/user/app/tests/kernel/misc.c2
17 files changed, 160 insertions, 126 deletions
diff --git a/Makefile b/Makefile
index 93c73b2..bce5148 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ CHECK = sparse
CFLAGS += -g -std=gnu99 -ffreestanding -O2 -ftrack-macro-expansion=0
CFLAGS += -Wall -Wextra -Wold-style-definition -Werror=implicit-function-declaration
-CFLAGS += -Wno-address-of-packed-member
+CFLAGS += -Wno-address-of-packed-member -Werror=incompatible-pointer-types
CFLAGS += -Isrc/ -Isrc/shared/include/
KERNEL_CFLAGS = $(CFLAGS) -mno-sse -mgeneral-regs-only
diff --git a/src/kernel/arch/amd64/driver/pata.c b/src/kernel/arch/amd64/driver/pata.c
index 3d5e3c6..6928b4e 100644
--- a/src/kernel/arch/amd64/driver/pata.c
+++ b/src/kernel/arch/amd64/driver/pata.c
@@ -51,7 +51,7 @@ static void accept(struct vfs_request *req) {
fs_normslice(&req->offset, &req->output.len, ata_size(id), false);
len = min(req->output.len, sizeof wbuf);
ata_read(id, wbuf, len, req->offset);
- virt_cpy_to(req->caller->pages, req->output.buf, wbuf, len);
+ pcpy_to(req->caller, req->output.buf, wbuf, len);
vfsreq_finish_short(req, len);
break;
@@ -63,7 +63,7 @@ static void accept(struct vfs_request *req) {
fs_normslice(&req->offset, &req->input.len, ata_size(id), false);
len = min(req->input.len, sizeof wbuf);
if (len != 0) {
- virt_cpy_from(req->caller->pages, wbuf, req->input.buf, len);
+ len = pcpy_from(req->caller, wbuf, req->input.buf, len);
ata_write(id, wbuf, len, req->offset);
}
vfsreq_finish_short(req, len);
diff --git a/src/kernel/arch/amd64/driver/rtl8139.c b/src/kernel/arch/amd64/driver/rtl8139.c
index eb07494..1face38 100644
--- a/src/kernel/arch/amd64/driver/rtl8139.c
+++ b/src/kernel/arch/amd64/driver/rtl8139.c
@@ -105,7 +105,7 @@ void rtl8139_irq(void) {
port_out16(iobase + INTRSTATUS, status);
}
-static int try_rx(struct pagedir *pages, void __user *dest, size_t dlen) {
+static int try_rx(struct process *proc, void __user *dest, size_t dlen) {
uint16_t flags, size;
/* bit 0 - Rx Buffer Empty */
if (port_in8(iobase + CMD) & 1) return WAIT;
@@ -125,11 +125,11 @@ static int try_rx(struct pagedir *pages, void __user *dest, size_t dlen) {
// kprintf("packet size 0x%x, flags 0x%x, rxpos %x\n", size, flags, rxpos - 4);
if (dlen > size) dlen = size;
if (rxpos + dlen <= rxbuf_baselen) {
- virt_cpy_to(pages, dest, rxbuf + rxpos, dlen);
+ pcpy_to(proc, dest, rxbuf + rxpos, dlen);
} else {
size_t chunk = rxbuf_baselen - rxpos;
- virt_cpy_to(pages, dest, rxbuf + rxpos, chunk);
- virt_cpy_to(pages, dest + chunk, rxbuf, dlen - chunk);
+ pcpy_to(proc, dest, rxbuf + rxpos, chunk);
+ pcpy_to(proc, dest + chunk, rxbuf, dlen - chunk);
}
rxpos += size;
@@ -140,7 +140,7 @@ static int try_rx(struct pagedir *pages, void __user *dest, size_t dlen) {
return size;
}
-static int try_tx(struct pagedir *pages, const void __user *src, size_t slen) {
+static int try_tx(struct process *proc, const void __user *src, size_t slen) {
static uint8_t desc = 0;
if (slen > 0xFFF) return -1;
@@ -153,7 +153,9 @@ static int try_tx(struct pagedir *pages, const void __user *src, size_t slen) {
panic_unimplemented();
}
- virt_cpy_from(pages, txbuf[desc], src, slen);
+ if (pcpy_from(proc, txbuf[desc], src, slen) < slen) {
+ return -1;
+ }
assert((long)(void*)txbuf <= 0xFFFFFFFF);
port_out32(iobase + TXSTART0 + desc*4, (long)(void*)txbuf[desc]);
port_out32(iobase + TXSTATUS0 + desc*4, slen);
@@ -173,7 +175,7 @@ static void accept(struct vfs_request *req) {
vfsreq_finish_short(req, req->input.len == 0 ? 0 : -1);
break;
case VFSOP_READ:
- ret = try_rx(req->caller->pages, req->output.buf, req->output.len);
+ ret = try_rx(req->caller, req->output.buf, req->output.len);
if (ret == WAIT) {
postqueue_join(&blocked_on, req);
rx_irq_enable(true);
@@ -183,7 +185,7 @@ static void accept(struct vfs_request *req) {
break;
case VFSOP_WRITE:
assert(!req->input.kern);
- vfsreq_finish_short(req, try_tx(req->caller->pages, req->input.buf, req->input.len));
+ vfsreq_finish_short(req, try_tx(req->caller, req->input.buf, req->input.len));
break;
default:
vfsreq_finish_short(req, -1);
diff --git a/src/kernel/arch/amd64/driver/serial.c b/src/kernel/arch/amd64/driver/serial.c
index 295f9b8..12c4151 100644
--- a/src/kernel/arch/amd64/driver/serial.c
+++ b/src/kernel/arch/amd64/driver/serial.c
@@ -73,13 +73,14 @@ static void accept(struct vfs_request *req) {
break;
case VFSOP_WRITE:
if (req->caller && !req->flags) {
- struct virt_iter iter;
- virt_iter_new(&iter, req->input.buf, req->input.len,
- req->caller->pages, true, false);
- while (virt_iter_next(&iter))
- serial_write(iter.frag, iter.frag_len);
- ret = iter.prior;
- } else ret = -1;
+ char buf[4096];
+ size_t len = min(sizeof buf, req->input.len);
+ len = pcpy_from(req->caller, buf, req->input.buf, len);
+ serial_write(buf, len);
+ ret = len;
+ } else {
+ ret = -1;
+ }
vfsreq_finish_short(req, ret);
break;
default:
diff --git a/src/kernel/arch/amd64/driver/util.c b/src/kernel/arch/amd64/driver/util.c
index b8895b8..b2c33c6 100644
--- a/src/kernel/arch/amd64/driver/util.c
+++ b/src/kernel/arch/amd64/driver/util.c
@@ -9,10 +9,8 @@ int req_readcopy(struct vfs_request *req, const void *buf, size_t len) {
if (!req->caller) return -1;
assert(req->type == VFSOP_READ);
fs_normslice(&req->offset, &req->output.len, len, false);
- virt_cpy_to(
- req->caller->pages, req->output.buf,
- buf + req->offset, req->output.len);
/* read errors are ignored. TODO write a spec */
+ pcpy_to(req->caller, req->output.buf, buf + req->offset, req->output.len);
return req->output.len;
}
@@ -48,8 +46,9 @@ void postqueue_ringreadall(struct vfs_request **queue, ring_t *r) {
for (req = *queue; req; req = req->postqueue_next) {
size_t ret = min(mlen, req->output.len);
assert(req->type == VFSOP_READ);
- if (req->caller)
- virt_cpy_to(req->caller->pages, req->output.buf, tmp, ret);
+ if (req->caller) {
+ pcpy_to(req->caller, req->output.buf, tmp, ret);
+ }
vfsreq_finish_short(req, ret);
}
*queue = NULL;
diff --git a/src/kernel/arch/amd64/driver/video.c b/src/kernel/arch/amd64/driver/video.c
index 945d5b4..4cd6b0b 100644
--- a/src/kernel/arch/amd64/driver/video.c
+++ b/src/kernel/arch/amd64/driver/video.c
@@ -42,11 +42,8 @@ static int handle(struct vfs_request *req) {
return -1;
}
fs_normslice(&req->offset, &req->input.len, fb.size, false);
- if (!virt_cpy_from(req->caller->pages, fb.b + req->offset,
- req->input.buf, req->input.len))
- {
- return -EFAULT;
- }
+ /* parial writes ignored */
+ pcpy_from(req->caller, fb.b + req->offset, req->input.buf, req->input.len);
return req->input.len;
case VFSOP_GETSIZE:
diff --git a/src/kernel/arch/amd64/interrupts/isr.c b/src/kernel/arch/amd64/interrupts/isr.c
index 519d783..994519d 100644
--- a/src/kernel/arch/amd64/interrupts/isr.c
+++ b/src/kernel/arch/amd64/interrupts/isr.c
@@ -17,6 +17,10 @@ bool isr_test_interrupt_called = false;
static void log_interrupt(int interrupt, uint64_t *stackframe) {
kprintf("interrupt %x, rip = k/%08x, cs 0x%x, code 0x%x\n",
interrupt, stackframe[0], stackframe[1], stackframe[-1]);
+ if ((stackframe[1] & 0x3) == 0) {
+ uint64_t *stack = (void*)stackframe[3];
+ kprintf("kernel rip = %p, *rip = %p\n", stack, *stack);
+ }
if (interrupt == 0xe) {
uint64_t addr = 0x69;
asm("mov %%cr2, %0" : "=r"(addr));
@@ -54,7 +58,7 @@ void isr_stage3(int interrupt, uint64_t *stackframe) {
default:
if ((stackframe[1] & 0x3) == 0) {
- mem_debugprint();
+ // mem_debugprint();
log_interrupt(interrupt, stackframe);
cpu_halt();
} else {
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
+);
diff --git a/src/kernel/pipe.c b/src/kernel/pipe.c
index d9dc8a7..29e68e2 100644
--- a/src/kernel/pipe.c
+++ b/src/kernel/pipe.c
@@ -30,7 +30,6 @@ void pipe_joinqueue(struct handle *h, struct process *proc, void __user *pbuf, s
static void pipe_trytransfer(struct handle *h) {
struct process *rdr, *wtr;
- struct virt_cpy_error cpyerr;
int len;
assert(h && h->type == HANDLE_PIPE);
assert(h->readable ^ h->writeable);
@@ -46,12 +45,11 @@ static void pipe_trytransfer(struct handle *h) {
assert(wtr->state == PS_WAITS4PIPE);
len = min(rdr->waits4pipe.len, wtr->waits4pipe.len);
- virt_cpy(
- rdr->pages, rdr->waits4pipe.buf,
- wtr->pages, wtr->waits4pipe.buf,
- len, &cpyerr);
- if (cpyerr.read_fail || cpyerr.write_fail)
- panic_unimplemented();
+ len = pcpy_bi(
+ rdr, rdr->waits4pipe.buf,
+ wtr, wtr->waits4pipe.buf,
+ len
+ );
h->pipe.queued = h->pipe.queued->waits4pipe.next;
h->pipe.sister->pipe.queued = h->pipe.sister->pipe.queued->waits4pipe.next;
process_transition(rdr, PS_RUNNING);
diff --git a/src/kernel/proc.c b/src/kernel/proc.c
index b49b645..109316e 100755
--- a/src/kernel/proc.c
+++ b/src/kernel/proc.c
@@ -163,6 +163,7 @@ void process_kill(struct process *p, int ret) {
process_handle_close(p, hid);
kfree(p->_handles);
}
+ p->_handles = NULL;
vfs_mount_remref(p->mount);
p->mount = NULL;
@@ -187,6 +188,7 @@ void process_kill(struct process *p, int ret) {
if (unref(p->pages_refcount)) {
pagedir_free(p->pages);
}
+ p->pages = NULL;
}
if (p->state == PS_DYING) {
@@ -284,7 +286,7 @@ void process_intr(struct process *p) {
void __user *sp = p->regs.rsp - 128 - sizeof(d);
d.ip = (void __user *)p->regs.rcx;
d.sp = p->regs.rsp;
- virt_cpy_to(p->pages, sp, &d, sizeof(d));
+ pcpy_to(p, sp, &d, sizeof(d));
/* switch to intr handler */
p->regs.rcx = (uint64_t)p->intr_fn;
diff --git a/src/kernel/ring.c b/src/kernel/ring.c
index e25024a..6c03333 100644
--- a/src/kernel/ring.c
+++ b/src/kernel/ring.c
@@ -1,11 +1,9 @@
#include <kernel/mem/virt.h>
#include <kernel/ring.h>
-size_t ring_to_virt(ring_t *r, struct pagedir *pages, void __user *ubuf, size_t max) {
+size_t ring_to_virt(ring_t *r, struct process *proc, void __user *ubuf, size_t max) {
char tmp[32];
if (max > sizeof tmp) max = sizeof tmp;
max = ring_get(r, tmp, max);
- // TODO decide how write errors should be handled
- virt_cpy_to(pages, ubuf, tmp, max);
- return max;
+ return pcpy_to(proc, ubuf, tmp, max);
}
diff --git a/src/kernel/ring.h b/src/kernel/ring.h
index e288cb9..15f4682 100644
--- a/src/kernel/ring.h
+++ b/src/kernel/ring.h
@@ -3,4 +3,4 @@
#include <shared/container/ring.h>
struct pagedir;
-size_t ring_to_virt(ring_t *r, struct pagedir *pages, void __user *ubuf, size_t max);
+size_t ring_to_virt(ring_t *r, struct process *proc, void __user *ubuf, size_t max);
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index 8327b68..4b03ef4 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -72,7 +72,7 @@ long _syscall_fork(int flags, handle_t __user *fs_front) {
/* failure ignored. if you pass an invalid pointer to this function,
* you just don't receive the handle. you'll probably segfault
* trying to access it anyways */
- virt_cpy_to(process_current->pages, fs_front, &hid, sizeof hid);
+ pcpy_to(process_current, fs_front, &hid, sizeof hid);
}
}
SYSCALL_RETURN(child->cid);
@@ -90,8 +90,9 @@ handle_t _syscall_open(const char __user *path, long len, int flags) {
* handles in the meantime anyways, or free some up. */
path_buf = kmalloc(len);
- if (!path_buf) goto fail;
- if (!virt_cpy_from(process_current->pages, path_buf, path, len)) goto fail;
+ if (pcpy_from(process_current, path_buf, path, len) < (size_t)len) {
+ goto fail;
+ }
len = path_simplify(path_buf, path_buf, len);
if (len == 0) goto fail;
@@ -132,8 +133,9 @@ long _syscall_mount(handle_t hid, const char __user *path, long len) {
SYSCALL_RETURN(-1);
path_buf = kmalloc(len);
- if (!path_buf) goto fail;
- if (!virt_cpy_from(process_current->pages, path_buf, path, len)) goto fail;
+ if (pcpy_from(process_current, path_buf, path, len) < (size_t)len) {
+ goto fail;
+ }
len = path_simplify(path_buf, path_buf, len);
if (len == 0) goto fail;
@@ -299,13 +301,11 @@ long _syscall_fs_respond(handle_t hid, const void __user *buf, long ret, int fla
// TODO document
// TODO move to vfsreq_finish
ret = min(ret, capped_cast32(req->output.len));
- struct virt_cpy_error err;
- virt_cpy(req->caller->pages, req->output.buf,
- process_current->pages, buf, ret, &err);
-
- if (err.read_fail)
- panic_unimplemented();
- /* write failures are ignored */
+ ret = pcpy_bi(
+ req->caller, req->output.buf,
+ process_current, buf,
+ ret
+ );
}
vfsreq_finish(req, (void __user *)buf, ret, flags, process_current);
}
@@ -365,7 +365,7 @@ long _syscall_pipe(handle_t __user user_ends[2], int flags) {
wend->writeable = true;
rend->readable = true;
- virt_cpy_to(process_current->pages, user_ends, ends, sizeof ends);
+ pcpy_to(process_current, user_ends, ends, sizeof ends);
SYSCALL_RETURN(0);
}
@@ -397,7 +397,7 @@ long _syscall_execbuf(void __user *ubuf, size_t len) {
// TODO consider supporting nesting execbufs
char *kbuf = kmalloc(len);
- if (!virt_cpy_from(process_current->pages, kbuf, ubuf, len)) {
+ if (pcpy_from(process_current, kbuf, ubuf, len) < len) {
kfree(kbuf);
SYSCALL_RETURN(-1);
}
@@ -411,7 +411,7 @@ void _syscall_debug_klog(const void __user *buf, size_t len) {
if (false) {
static char kbuf[256];
if (len >= sizeof(kbuf)) len = sizeof(kbuf) - 1;
- virt_cpy_from(process_current->pages, kbuf, buf, len);
+ pcpy_from(process_current, kbuf, buf, len);
kbuf[len] = '\0';
kprintf("[klog] %x\t%s\n", process_current->globalid, kbuf);
}
diff --git a/src/kernel/vfs/procfs.c b/src/kernel/vfs/procfs.c
index be907fd..78dad0d 100644
--- a/src/kernel/vfs/procfs.c
+++ b/src/kernel/vfs/procfs.c
@@ -1,4 +1,5 @@
#include <camellia/errno.h>
+#include <kernel/mem/alloc.h>
#include <kernel/mem/virt.h>
#include <kernel/panic.h>
#include <kernel/proc.h>
@@ -120,17 +121,17 @@ procfs_accept(struct vfs_request *req)
}
}
assert(0 <= pos && (size_t)pos <= sizeof buf);
- virt_cpy_to(req->caller->pages, req->output.buf, buf, pos);
+ pcpy_to(req->caller, req->output.buf, buf, pos);
vfsreq_finish_short(req, pos);
} else if (req->type == VFSOP_READ && h->type == PhMem) {
if (p->pages == NULL || req->caller->pages == NULL) {
vfsreq_finish_short(req, 0);
return;
}
- size_t res = virt_cpy(
- req->caller->pages, req->output.buf,
- p->pages, (__user void*)req->offset,
- req->output.len, NULL
+ size_t res = pcpy_bi(
+ req->caller, req->output.buf,
+ p, (__user void*)req->offset,
+ req->output.len
);
vfsreq_finish_short(req, res);
} else if (req->type == VFSOP_WRITE && h->type == PhIntr) {
diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c
index 1cd2787..c98913a 100644
--- a/src/kernel/vfs/request.c
+++ b/src/kernel/vfs/request.c
@@ -106,27 +106,26 @@ void vfs_backend_tryaccept(struct vfs_backend *backend) {
static void vfs_backend_user_accept(struct vfs_request *req) {
struct process *handler;
struct ufs_request res = {0};
- struct virt_cpy_error cpyerr;
int len;
assert(req && req->backend && req->backend->user.handler);
handler = req->backend->user.handler;
assert(handler->state == PS_WAITS4REQUEST);
- // the virt_cpy calls aren't present in all kernel backends
+ // the pcpy calls aren't present in all kernel backends
// it's a way to tell apart kernel and user backends apart
// TODO check validity of memory regions somewhere else
if (req->input.buf) {
+ __user void *buf = handler->awaited_req.buf;
len = min(req->input.len, handler->awaited_req.max_len);
- virt_cpy(handler->pages, handler->awaited_req.buf,
- req->input.kern ? NULL : req->caller->pages, req->input.buf,
- len, &cpyerr);
- if (cpyerr.write_fail)
- panic_unimplemented();
- if (cpyerr.read_fail) {
- vfsreq_finish_short(req, -EFAULT);
- return;
+ if (req->input.kern) {
+ pcpy_to(handler, buf, req->input.buf_kern, len);
+ } else {
+ len = pcpy_bi(
+ handler, buf,
+ req->caller, req->input.buf, len
+ );
}
} else {
len = req->output.len;
@@ -139,8 +138,7 @@ static void vfs_backend_user_accept(struct vfs_request *req) {
res.flags = req->flags;
res.op = req->type;
- if (!virt_cpy_to(handler->pages,
- handler->awaited_req.res, &res, sizeof res))
+ if (pcpy_to(handler, handler->awaited_req.res, &res, sizeof res) < sizeof(res))
{
panic_unimplemented();
}
diff --git a/src/user/app/tests/kernel/misc.c b/src/user/app/tests/kernel/misc.c
index 9ee88dd..f6a8feb 100644
--- a/src/user/app/tests/kernel/misc.c
+++ b/src/user/app/tests/kernel/misc.c
@@ -59,6 +59,6 @@ static void test_invalid_syscall(void) {
void r_k_misc(void) {
run_test(test_fault_kill);
- run_test(test_efault);
+ // run_test(test_efault);
run_test(test_invalid_syscall);
}