aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-07-07 21:47:14 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-07-07 21:47:14 +0300
commit219c27d420fe0abe5515cefc2513c6fe60aafdf9 (patch)
tree5cd0c38a971245c91fd7bc3539b4a37c8a08a7f1
parentfe4c623cb9320226866829317cea8ba0c49e7dbc (diff)
downloadkmi-219c27d420fe0abe5515cefc2513c6fe60aafdf9.tar.gz
kmi-219c27d420fe0abe5515cefc2513c6fe60aafdf9.zip
add req_page back in as I realized it's useful
+ Can be used to pass contiguous memory regions to things like virtio block devices for implementing disk drivers etc.
-rwxr-xr-xarch/riscv64/conf/initbin3960 -> 3968 bytes
-rw-r--r--arch/riscv64/conf/init.c14
-rw-r--r--arch/riscv64/conf/initrdbin4608 -> 4608 bytes
-rw-r--r--arch/riscv64/kernel/proc.c2
-rw-r--r--include/kmi/syscalls.h9
-rw-r--r--include/kmi/uapi.h20
-rw-r--r--include/kmi/vmem.h8
-rw-r--r--src/debug.c5
-rw-r--r--src/uapi/dispatch.c1
-rw-r--r--src/uapi/mem.c28
-rw-r--r--src/vmem.c28
11 files changed, 100 insertions, 15 deletions
diff --git a/arch/riscv64/conf/init b/arch/riscv64/conf/init
index 5248f8f..b378582 100755
--- a/arch/riscv64/conf/init
+++ b/arch/riscv64/conf/init
Binary files differ
diff --git a/arch/riscv64/conf/init.c b/arch/riscv64/conf/init.c
index c3e8334..c4e8064 100644
--- a/arch/riscv64/conf/init.c
+++ b/arch/riscv64/conf/init.c
@@ -277,12 +277,12 @@ static void sys_sleep()
#define CSR_CYCLE "0xc00"
-static void handle_kernel(long a0, long a1, long d0, long d1, long d2, long d3)
+static void handle_kernel(long pid, long tid, long d0, long d1, long d2,
+ long d3)
{
- if (a1 != SYS_USER_BOOTED)
+ if (d0 != SYS_USER_BOOTED)
return;
- long tid = d0;
if (tid != 1) {
puts("Woo, more cores!\n");
while (1)
@@ -311,11 +311,11 @@ static void handle_kernel(long a0, long a1, long d0, long d1, long d2, long d3)
print_value("Executed cycles per second", cend - cstart);
puts("Starting fork():\n");
- long pid = sys_fork();
- if (pid != 0) {
- print_value("Child pid", pid);
+ long cid = sys_fork();
+ if (cid != 0) {
+ print_value("Child pid", cid);
puts("Swapping to child...\n");
- while(1) sys_swap(pid);
+ while(1) sys_swap(cid);
}
puts("Hello from child!\n");
diff --git a/arch/riscv64/conf/initrd b/arch/riscv64/conf/initrd
index bc0858e..4647812 100644
--- a/arch/riscv64/conf/initrd
+++ b/arch/riscv64/conf/initrd
Binary files differ
diff --git a/arch/riscv64/kernel/proc.c b/arch/riscv64/kernel/proc.c
index 413c078..f21ce5c 100644
--- a/arch/riscv64/kernel/proc.c
+++ b/arch/riscv64/kernel/proc.c
@@ -35,7 +35,7 @@ void run_init(struct tcb *t, vm_t fdt, vm_t initrd)
"li a2, %3\n"
"mv a3, %4\n"
"mv a4, %5\n"
- "li a5, %6\n"
+ "li a5, %6\n"
"sret\n"
:
: "r" (stack_top),
diff --git a/include/kmi/syscalls.h b/include/kmi/syscalls.h
index 0826a6b..eece89e 100644
--- a/include/kmi/syscalls.h
+++ b/include/kmi/syscalls.h
@@ -47,18 +47,21 @@ enum sys_code {
/** Request memory from anywhere. */
SYS_REQ_MEM,
- /** Request physical page from ram. */
- SYS_REF_SHAREDMEM,
-
/** Request memory with physical address. */
SYS_REQ_PMEM,
/** Request memory at fixed virtual address. */
SYS_REQ_FIXMEM,
+ /** Request one page of memory, useful for stuff like virtio buffers */
+ SYS_REQ_PAGE,
+
/** Request shared memory. */
SYS_REQ_SHAREDMEM,
+ /** Request physical page from ram. */
+ SYS_REF_SHAREDMEM,
+
/** Free memory. */
SYS_FREE_MEM,
/** @} */
diff --git a/include/kmi/uapi.h b/include/kmi/uapi.h
index 53ae9cb..8047632 100644
--- a/include/kmi/uapi.h
+++ b/include/kmi/uapi.h
@@ -324,6 +324,26 @@ SYSCALL_DECLARE3(ref_sharedmem, tid, addr, flags);
SYSCALL_DECLARE3(req_pmem, paddr, size, flags);
/**
+ * Get physically contiguous region of memory, useful for stuff like virtio
+ * buffers.
+ *
+ * @param t Current tcb.
+ * @param size Minimum size of region.
+ * @param flags Flags of allocation.
+ * @param c Unused.
+ * @param d Unused.
+ * @param e Unused.
+ *
+ * Return\ref OK and start of virtual address, start of physical address and
+ * size, in that order.
+ *
+ * @note Users are encouraged to check the return size, as it may be
+ * significantly larger than requested, in which case it is recommended to place
+ * multiple buffers in the region if required by the application.
+ */
+SYSCALL_DECLARE2(req_page, size, flags);
+
+/**
* Request fixed memory syscall.
*
* Allocates at least the specified size of allocation which includes the start
diff --git a/include/kmi/vmem.h b/include/kmi/vmem.h
index 3f7ab71..dd968ca 100644
--- a/include/kmi/vmem.h
+++ b/include/kmi/vmem.h
@@ -30,16 +30,18 @@ vm_t alloc_uvmem(struct tcb *r, size_t size, vmflags_t flags);
/**
* Allocate one physical page for user virtual memory.
+ * Useful for virtio buffers etc. I'm repeating myself quite a lot with these
+ * doxygen descriptions, aren't I?
*
* @param r Process to allocate memory in.
* @param size Minimum size of allocation.
* @param flags Flags of allocation.
- * @param asize Where to write actual size of allocation.
- * @param paddr Where to write physical address of page.
+ * @param startp Address of allocated physical page.
+ * @param sizep Actual size of page.
* @return Start of allocation when succesful, \c NULL otherwise.
*/
vm_t alloc_uvpage(struct tcb *r, size_t size, vmflags_t flags,
- size_t *asize, pm_t *paddr);
+ pm_t *startp, size_t *sizep);
/**
* Allocate fixed user virtual memory.
diff --git a/src/debug.c b/src/debug.c
index 9573bbc..567911b 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -753,7 +753,10 @@ void dbg(const char *fmt, ...)
if (is_set(flags, PRECS_FLAG))
i = precision;
- chars_written += __puts(s);
+ for (; *s && i--;) {
+ __putchar(*s++);
+ chars_written++;
+ }
fmt++;
break;
diff --git a/src/uapi/dispatch.c b/src/uapi/dispatch.c
index 16a17d2..4135171 100644
--- a/src/uapi/dispatch.c
+++ b/src/uapi/dispatch.c
@@ -50,6 +50,7 @@ void handle_syscall(sys_arg_t syscall, sys_arg_t a, sys_arg_t b,
case SYS_PUTCH: sys_putch(t, a, b, c, d, e); break;
case SYS_REQ_MEM: sys_req_mem(t, a, b, c, d, e); break;
case SYS_REQ_PMEM: sys_req_pmem(t, a, b, c, d, e); break;
+ case SYS_REQ_PAGE: sys_req_page(t, a, b, c, d, e); break;
case SYS_REQ_FIXMEM: sys_req_fixmem(t, a, b, c, d, e); break;
case SYS_REQ_SHAREDMEM: sys_req_sharedmem(t, a, b, c, d, e); break;
case SYS_REF_SHAREDMEM: sys_ref_sharedmem(t, a, b, c, d, e); break;
diff --git a/src/uapi/mem.c b/src/uapi/mem.c
index 17823a1..49370fc 100644
--- a/src/uapi/mem.c
+++ b/src/uapi/mem.c
@@ -106,6 +106,34 @@ SYSCALL_DEFINE3(req_pmem)(struct tcb *t, sys_arg_t paddr, sys_arg_t size,
}
/**
+ * Allocate some contiguous region in memory.
+ * Due to page allocation constraints, this is generally just one page that's
+ * larger than the \p size parameter. Should work fine for 4K - 2M allocations,
+ * which I assume is generally what is used, but we'll see if I have to
+ * implement an actually good page allocator at some point.
+ *
+ * @param t Current tcb.
+ * @param size Minimum size of mapping.
+ * @param flags Flags of mapping. Unsure why you'd want anything besides VM_W |
+ * VM_R, but eh.
+ *
+ * @return \see sys_req_page().
+ */
+SYSCALL_DEFINE2(req_page)(struct tcb *t, sys_arg_t size, sys_arg_t flags)
+{
+ struct tcb *r = get_cproc(t);
+
+ pm_t addr = 0;
+ vm_t start = 0;
+ size_t asize = 0;
+ flags = sanitize_uvflags(flags);
+ if (!(start = alloc_uvpage(r, size, flags, &addr, &asize)))
+ return_args1(t, ERR_OOMEM);
+
+ return_args4(t, OK, start, addr, asize);
+}
+
+/**
* Request shared memory syscall handler.
*
* @param t Current tcb.
diff --git a/src/vmem.c b/src/vmem.c
index 27e1b2f..261ef42 100644
--- a/src/vmem.c
+++ b/src/vmem.c
@@ -279,6 +279,34 @@ vm_t map_fixed_uvmem(struct tcb *t, pm_t start, size_t size, vmflags_t flags)
return v + (start % BASE_PAGE_SIZE);
}
+vm_t alloc_uvpage(struct tcb *t, size_t size, vmflags_t flags, pm_t *startp,
+ size_t *sizep)
+{
+ enum mm_order order = nearest_order(size);
+ size = order_size(order);
+
+ const vm_t v = alloc_region(&t->uvmem.region, size, &size, flags);
+ if (!v)
+ return 0;
+
+ pm_t start = alloc_page(order);
+ if (!start) {
+ free_region(&t->uvmem.region, size);
+ return 0;
+ }
+
+ if (map_fixed_region(t->proc.vmem, v, start, size, flags)) {
+ unmap_region(t->proc.vmem, v, size);
+ free_region(&t->uvmem.region, v);
+ return NULL;
+ }
+
+ *startp = (pm_t)__pa(start);
+ *sizep = size;
+ return v;
+}
+
+
/* free_shared_uvmem shouldn't be needed, likely to work with free_uvmem */
vm_t alloc_shared_uvmem(struct tcb *s, size_t size, vmflags_t flags)
{