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. --- src/debug.c | 5 ++++- src/uapi/dispatch.c | 1 + src/uapi/mem.c | 28 ++++++++++++++++++++++++++++ src/vmem.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 1 deletion(-) (limited to 'src') 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