From 219c27d420fe0abe5515cefc2513c6fe60aafdf9 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sun, 7 Jul 2024 21:47:14 +0300 Subject: 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. --- arch/riscv64/conf/init | Bin 3960 -> 3968 bytes arch/riscv64/conf/init.c | 14 +++++++------- arch/riscv64/conf/initrd | Bin 4608 -> 4608 bytes arch/riscv64/kernel/proc.c | 2 +- include/kmi/syscalls.h | 9 ++++++--- include/kmi/uapi.h | 20 ++++++++++++++++++++ include/kmi/vmem.h | 8 +++++--- src/debug.c | 5 ++++- src/uapi/dispatch.c | 1 + src/uapi/mem.c | 28 ++++++++++++++++++++++++++++ src/vmem.c | 28 ++++++++++++++++++++++++++++ 11 files changed, 100 insertions(+), 15 deletions(-) diff --git a/arch/riscv64/conf/init b/arch/riscv64/conf/init index 5248f8f..b378582 100755 Binary files a/arch/riscv64/conf/init and b/arch/riscv64/conf/init 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 Binary files a/arch/riscv64/conf/initrd and b/arch/riscv64/conf/initrd 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 @@ -323,6 +323,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. * 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 @@ -105,6 +105,34 @@ SYSCALL_DEFINE3(req_pmem)(struct tcb *t, sys_arg_t paddr, sys_arg_t size, return_args2(t, OK, start); } +/** + * 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. * 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) { -- cgit v1.3