rc2014: add external buffer cache
authorAlan Cox <alan@linux.intel.com>
Sat, 6 Oct 2018 19:28:55 +0000 (20:28 +0100)
committerAlan Cox <alan@linux.intel.com>
Sat, 6 Oct 2018 19:28:55 +0000 (20:28 +0100)
That lets us go up to 16K of buffers that are also unmapped when not being
accessed. Lots more meta data cached and a nicer system feel.

Kernel/platform-rc2014/buffers.s [new file with mode: 0644]
Kernel/platform-rc2014/extbuffer.c [new file with mode: 0644]

diff --git a/Kernel/platform-rc2014/buffers.s b/Kernel/platform-rc2014/buffers.s
new file mode 100644 (file)
index 0000000..73e2c0b
--- /dev/null
@@ -0,0 +1,67 @@
+;
+;      External buffer support logic
+;
+
+       .module buffers
+       .area _COMMONMEM
+
+       .include "../kernel.def"
+       .include "kernel.def"
+
+       .globl _do_blkzero
+       .globl _do_blkcopyk
+       .globl _do_blkcopyul
+       .globl _do_blkcopyuh
+
+       .globl _bdest
+       .globl _blen
+
+       .globl map_kernel
+       .globl map_buffers
+       .globl map_buffers_user
+       .globl map_buffers_user_h
+
+       .globl _workbuf
+
+
+;
+;      Ugly - but we need to rework memory management and stuff to fix it
+;
+_workbuf:
+       .ds 1024
+
+_bdest:
+       .word 0
+_blen:
+       .word 0
+
+_do_blkzero:
+       call map_buffers
+       ld e,l
+       ld d,h
+       inc de
+       ld (hl),#0
+       ld bc,#511
+       ldir
+       jp map_kernel
+
+_do_blkcopyk:
+       call map_buffers
+       ld de,(_bdest)
+       ld bc,(_blen)
+       ldir
+       jp map_kernel
+
+_do_blkcopyul:
+       call map_buffers_user
+       ld de,(_bdest)
+       ld bc,(_blen)
+       ldir
+       jp map_kernel
+
+_do_blkcopyuh:
+       call map_buffers_user_h
+       ld de,(_bdest)
+       ld bc,(_blen)
+       ldir
+       jp map_kernel
diff --git a/Kernel/platform-rc2014/extbuffer.c b/Kernel/platform-rc2014/extbuffer.c
new file mode 100644 (file)
index 0000000..28cb97c
--- /dev/null
@@ -0,0 +1,133 @@
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+
+extern uint8_t *bdest;
+extern uint16_t blen;
+extern void do_blkzero(uint8_t *ptr) __z88dk_fastcall;
+extern void do_blkcopyk(uint8_t *src) __z88dk_fastcall;
+extern void do_blkcopyul(uint8_t *src) __z88dk_fastcall;
+extern void do_blkcopyuh(uint8_t *src) __z88dk_fastcall;
+
+/*
+ *     Must live in CODE2
+ */
+
+void blktok(void *kaddr, struct blkbuf *buf, uint16_t off, uint16_t len)
+{
+    bdest = kaddr;
+    blen = len;
+    do_blkcopyk(buf->__bf_data + off);
+}
+
+void blkfromk(void *kaddr, struct blkbuf *buf, uint16_t off, uint16_t len)
+{
+    bdest = buf->__bf_data + off;
+    blen = len;
+    do_blkcopyk(kaddr);
+}
+
+/* FIXME: work out a nice way to share the logic */
+void blktou(void *uaddr, struct blkbuf *buf, uint16_t off, uint16_t len)
+{
+    uint16_t split;
+    bdest = uaddr;
+    blen = len;
+    /* If it's all below 16K or all over 32K then use the 0x4000 window */
+    if ((uint16_t)uaddr + len < 0x4000 || (uint16_t)uaddr > 0x8000) {
+        do_blkcopyul(buf->__bf_data + off);
+        return;
+    }
+    /* If it's all below 0x8000 then use the 0x8000 window */
+    if ((uint16_t)uaddr + len < 0x8000) {
+        do_blkcopyuh(buf->__bf_data + off + 0x4000);
+        return;
+    }
+    /* Split case */
+    split = 0x8000 - (uint16_t)uaddr;
+    blen = split;
+    do_blkcopyuh(buf->__bf_data + off + 0x4000);
+    blen = len - split;
+    bdest += split;
+    do_blkcopyul(buf->__bf_data + off + split);
+}
+
+void blkfromu(void *uaddr, struct blkbuf *buf, uint16_t off, uint16_t len)
+{
+    uint16_t split;
+    bdest = buf->__bf_data + off;
+    blen = len;
+    /* If it's all below 16K or all over 32K then use the 0x4000 window */
+    if ((uint16_t)uaddr + len < 0x4000 || (uint16_t)uaddr > 0x8000) {
+        do_blkcopyul(uaddr);
+        return;
+    }
+    /* If it's all below 0x8000 then use the 0x8000 window */
+    if ((uint16_t)uaddr + len < 0x8000) {
+        bdest += 0x4000;
+        do_blkcopyuh(uaddr);
+        return;
+    }
+    /* Split case */
+    split = 0x8000 - uaddr;
+    blen = split;
+    bdest += 0x4000;
+    do_blkcopyuh(uaddr);
+    blen = len - split;
+    bdest += split- 0x4000;
+    do_blkcopyul((uint8_t *)uaddr + split);
+}
+
+static uint8_t scratchbuf[64];
+
+/* Worst case is needing to copy over about 64 bytes */
+void *blkptr(struct blkbuf *buf, uint16_t offset, uint16_t len)
+{
+    if (len > 64)
+        panic("blkptr");
+    bdest = scratchbuf;
+    blen = sizeof(scratchbuf);
+    do_blkcopyk(buf->__bf_data + offset);
+    return scratchbuf;
+}
+
+void blkzero(struct blkbuf *buf)
+{
+    do_blkzero(buf->__bf_data);
+}
+
+/*
+ *     Scratch buffers for syscall arguments - until we can rework
+ *     execve and realloc to avoid this need
+ *
+ *     The buffers must be valid in both kernel and buffer mappings.
+ */
+
+extern uint8_t workbuf[2][BLKSIZE];
+static uint8_t tfree = 3;
+
+void tmpfree(void *p)
+{
+  if (p == workbuf[0]) {
+      tfree |= 1;
+      return;
+  }
+  if (p == workbuf[1]) {
+      tfree |= 2;
+      return;
+  }
+  panic("tmpfree");
+}
+
+void *tmpbuf(void)
+{
+   if (tfree & 1) {
+       tfree &= ~1;
+       return workbuf[0];
+   }
+   if (tfree & 2) {
+       tfree &= ~2;
+       return workbuf[1];
+   }
+   panic("tmpbuf");
+}