summaryrefslogtreecommitdiff
path: root/src/kernel/arch
diff options
context:
space:
mode:
authordzwdz2023-01-25 01:02:04 +0100
committerdzwdz2023-01-25 01:04:49 +0100
commit2a2fc4dffe0117ce874a6cf1dcc34321ed8add77 (patch)
treeaf1e24f72241dbbff97797b9e186f7d27b5b54b4 /src/kernel/arch
parent52e7fe3c679469032e77a5ca4adf19618ba1201b (diff)
kernel/virt: replace the virt_cpy api with a more foolproof one
Diffstat (limited to 'src/kernel/arch')
-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
6 files changed, 31 insertions, 28 deletions
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 {